🎅 🎅 🎅 站在 Vue3 上-构建管理系统 vue-vite-admin-ts

2021-12-24 19:34:26 +08:00
 vipbic

出发点的本质是想学习下 vue3 、vite 、typescript 、以及在创建企业管理后台菜单权限控制、路由控制、组件设计、网络异步组件、hook 意义、构建编译、设计模式的集合,对自己使用学习新技术的认知和见解,也是对自己在以往的知识点的掌握做出一个总结

新建项目

既然出发点奔着 vite ,当然我们得先安装 vite

Vite 需要 Node.js 版本 >= 12.0.0

# 安装 vite
npm init vite@latest 

# npm 6.x
npm init vite@latest my-vue-app --template vue # 拉取模板 -- 官网提供更多模板选择

# npm 7+, 需要额外的双横线:
npm init vite@latest my-vue-app -- --template vue # 拉取模板 -- 官网提供更多模板选择

官方文档-如何安装 vite

项目安装完成后,在 package.json 中会出现三条我们所常见配置命令

{
    "scripts": {
        "dev": "vite",
        // 启动开发服务器,别名:`vite dev`,`vite serve`
        "build": "vite build",
        // 为生产环境构建产物
        "preview": "vite preview"
        // 本地预览生产构建产物
    }
}

启动服务

# 安装依赖
npm install 

# 启动服务
npm run dev 

上述不出意外的出现端口 3000 的端口,即访问 http://localhost:3000/

项目地址

🎉🎉🎉🎉🎉GitHub

项目预览

🎉🎉🎉🎉🎉在线预览

构建布局

src/main.js

import {createApp} from 'vue'
import App from './App.vue'
import router from '@/packages/router'
import setupInit from '@/packages/base/index'
import mitt from "mitt";

const app = createApp(App)
app.provide("$mitt", mitt());
setupInit(app)
router.isReady().then(() => {
    app.mount('#app')
})

最终布局文件请看packages/layout/index.vue


<template>
    <a-layout style="height: 100%">
        <Slider/>
        <a-layout :style="{marginLeft}" class="layout" :class="layoutClassName">
            <HeaderTop/>
            <HeaderProcess/>
            <LayoutContainer/>
        </a-layout>
    </a-layout>
</template>

路由介绍

Vue Router4 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举。功能包括:

具体文件请看packages/router/index.ts

import {createRouter, createWebHashHistory, createWebHistory, RouteRecordRaw, RouterOptions} from 'vue-router'
import {routerMode} from '@/packages/config';
import {App} from 'vue';
import {setupRouterGuard} from '@/packages/router/guard'
import {setupBeforeStore} from "@/packages/router/beforeStore";
import {setAddRoute} from '@/packages/router/addRoute'

// 定义路由
const routes: Array<RouteRecordRaw> = [
    {
        path: "/",
        name: "admin",
        component: () => import('@/packages/layout/index.vue'),
        children: [
            {path: '', redirect: 'home'},
            {
                path: '/home', name: 'home', meta: {title: '首页'},
                component: () => import('@/packages/views/home/index.vue')
            },
        ]
    },
    {
        path: "/login", name: 'login', meta: {title: '登录'},
        component: () => import('@/packages/views/login/index.vue'),
    },
    {
        path: "/test", name: 'test', meta: {title: '测试页面'},
        component: () => import('@/packages/views/test/index.vue'),
    },
    {
        path: '/404',
        component: () => import('@/packages/views/error/404.vue'),
    },
    {
        path: '/:catchAll(.*)*', // 不识别的 path 自动匹配 404
        redirect: '/404',
    },
]

// 实列化 router
const router = createRouter({
    history: routerMode === 'history' ? createWebHistory() : createWebHashHistory(),
    routes
})


router.beforeEach((to: any, from: any, next: any) => {
    setupBeforeStore()
    setupRouterGuard(to, from, next)
});

const setupRouter = (app: App) => {
    setAddRoute(app, router)
    app.use(router)
}

export default router;
export {
    setupRouter
}

Vuex

Vuex4 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化

具体文件请看packages/store/index.ts

import type {App} from 'vue';
import {createStore} from 'vuex'
import user from './user'
import app from './app'
import {setAddStore} from "@/packages/store/addStore";


const store: any = createStore({
    modules: {
        user,
        app
    }
})


const setupStore = (app: App) => {
    setAddStore(app, store)
    app.use(store)
}

export {
    setupStore
}
export default store;

axios

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中,

此处代码还应有响应拦截,请求拦截,没有粘贴出来,具体请看packages/http/request.ts,自动重连,错误返回,封装了常见的请求使用方式


const post = (url: string, params, config) => {
    return http.post(rewriteUrl(url), params, config)
}

const get = (url: string, params, config) => {
    return http.get(rewriteUrl(url), {params: params, ...config})
}


const all = (request: Array<any>) => {
    return axios.all(request)
}


const upload = (url: string, params) => {
    let config = {
        headers: {
            "Content-Type": "multipart/form-data",
        },
    };
    return http.post(rewriteUrl(url), params, config);
};


const download = (url: string, params, config) => {
    return axios({
        method: "post",
        url: rewriteUrl(url), //后端下载接口地址
        responseType: "blob", // 设置接受的流格式
        data: {
            ...params,
        },
        params: {
            ...params
        }
    }).then((res: any) => {
        handleExport(res.data, config.fileName);
    })
};


export {
    post,
    get,
    all,
    upload,
    download,
}

目录介绍

egg

提供基础服务,主要菜单编辑这块,动态加载路由,完整的增删改查,具体代码请看egg/app/controller/home.js

cd /vue-vite-admin-ts/egg
npm install // 安装 egg.js 所需要的依赖
npm run dev // 开发模式 
npm run serve // 服务模式

获取项目后,打开 egg/config/config.default.js 请在 username 填写自己的数据名

config.sequelize = {
    dialect: 'mysql',
    host: '127.0.0.1',
    port: 3306,
    username: 'xxxx', // 数据库用户名
    password: '**123456**', // 数据库密码
    database: 'egg',
    define: { // model 的全局配置
        timestamps: true, // 添加 create,update,delete 时间戳
        paranoid: false, // 添加软删除
        freezeTableName: true, // 防止修改表名为复数
        underscored: false // 防止驼峰式字段被默认转为下划线
    }
}

mock 目录

众所周知 Mock.js 因为两个重要的特性风靡前端:

Mock.mock("/api/yxs/notice", 'post', () => {
    const data = Mock.mock({
        "array|5": [
            {
                id: "@id", // 随机 id
                text: "@cword(10)", // 随机文本
                createTime: "@datetime(MM-dd HH:mm:ss)",
            }
        ]
    })
    // 指定规则统一数据格式
    const result: resData = {
        code: 1,
        message: '请求成功',
        data: data.array,
    }
    return result;
})

使用 mock ,只需在 main.js 文件中引入即可

src

放置源码目录

├── src                                 // 源码目录
    |────packages                           // 应用主资源
    |──assets                               // 图片等资源
    |──base                                 // 基础配置
    |──common                               // 处理公共函数
    |──components                           // 全局组件
    |──config                               // 配置入口
    |──extend                               // 扩展目录
    |──hook                                 // 放置钩子函数
    |──http                                 // 网络请求
    |──layout                               // 布局
    |──plugin                               // 插件
    |──router                               // 路由
    |──service                              // 请求接口
    |──store                                // 数据存储
    |──style                                // 样式入口
    |──theme                                // 主题
    |──utils                                // 公共工具方法
    |──views                                // 页面组件
    |──install.ts                           // 应用入口文件
    |──App.vue                              // 入口组件
    |──main.ts                              // 默认应用文件(lib.html)

typings 目录

放置在 typescript 环境中开发,全局变量,避免编辑器提示报错

export {};
declare global {
    declare interface Window {
        __app__: any,
        $: any,
        less: any
    }
}

文件介绍

.editorconfig

editorconfig 是用于跨不同的编辑器和 IDE 为多个开发人员维护一致的编码风格的配置文件。editorconfig 项目由定义编码样式的文件格式和一组文本编辑器插件组成,编辑器插件通过读取文件并以已定义的样式格式化指定文件。 editorconfig 文件具有友好的阅读性,且能与版本控制系统配合良好的特点

root = true

[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

.eslintignore

eslin 检查代码过滤文件

/examples
/html
/lib/*
/public

/test
/mock
/egg/*
/dist
/typings
*.sh
node_modules

iconfont.*
*.md
*.scss
*.woff
*.ttf
vite.config.ts

.eslintrc.js

在 JavaScript 20 多年的发展历程中,也出现过许许多多的 lint 工具,下面就来介绍下主流的三款 lint 工具,

ESLint 号称下一代的 JS Linter 工具,它的灵感来源于 PHP Linter ,将源代码解析成 AST ,然后检测 AST 来判断代码是否符合规则。ESLint 使用 esprima 将源代码解析吃成 AST ,然后你就可以使用任意规则来检测 AST 是否符合预期,这也是 ESLint 高可扩展性的原因

module.exports = {
    rules: {
        // 缩进 4 空格
        "indent": [2, 4],

        // 禁止空格和 tab 的混合缩进
        'no-mixed-spaces-and-tabs': 1,

        // 禁用 debugger
        'no-debugger': 1,

        // 禁止不必要的布尔转换
        'no-extra-boolean-cast': 1,

        // 强制所有控制语句使用一致的括号风格
        'curly': 1,

        // 禁止使用多个空格 c
        'no-multi-spaces': 1,

        // 要求在函数标识符和其调用之间有空格
        'func-call-spacing': 1,

        // 关闭 强制在函数括号内使用一致的换行
        'function-paren-newline': 0,

        // 强制隐式返回的箭头函数体的位置
        'implicit-arrow-linebreak': 1,

        // 强制在对象字面量的属性中键和值之间使用一致的间距
        'key-spacing': 1,

        // 强制在关键字前后使用一致的空格
        'keyword-spacing': 1,

        // 要求调用无参构造函数时有圆括号
        'new-parens': 1,

        // 禁止出现多行空行
        'no-multiple-empty-lines': 1,

        // 不检查后面是否有分号
        'semi': 0,

        // 要求操作符周围有空格
        'space-infix-ops': 1,

        //数组中不允许出现空位置
        'no-sparse-arrays': 2,

        // 不允许有声明后未使用的变量或者参数
        'no-unused-vars': 'off',

        'vue/script-setup-uses-vars': 'off',  // 如果使用 script-setup 可開啟

        'vue/component-definition-name-casing': 'off' // 驼峰命名
    },
}

.huskyrc

Husky 可以防止错误的 git commit ,git push 和更多 woof !

主要用于检查代码是否通过在提交,防止团队出现不规范的代码

// package.json
{
  "husky": {
        "hooks": {
            "pre-commit": "lint-staged"
        }
    },
    "lint-staged": {
        "*.{vue, ts}": [
            "eslint --quiet",
            "git add"
        ]
    },
}
git commit -m '测试提交' 

.npmrc

.npmrc ,可以理解成 npm running cnfiguration, 即 npm 运行时配置文件

在项目的根目录下新建 .npmrc 文件,在里面以 key=value 的格式进行配置。比如要把 npm 的源配置为淘宝源, 设置代理

registry = https://registry.npmjs.org/

当然你可以手动设置

config set registry https://registry.npm.taobao.org

.prettierrc

vsCode 使用 prettier 扩展,结合 .prettierrc 配置文件格式化代码

module.exports = {
    // 一行最多 100 字符
    printWidth: 100,
    // 使用 4 个空格缩进
    tabWidth: 4,
    // 不使用缩进符,而使用空格
    useTabs: false,
    // 行尾不需要有分号
    semi: false,
    // 使用单引号
    singleQuote: true,
    // 对象的 key 仅在必要时用引号
    quoteProps: 'as-needed',
    // jsx 不使用单引号,而使用双引号
    jsxSingleQuote: false,
    // 尾随逗号
    trailingComma: 'all',
    // 大括号内的首尾需要空格
    bracketSpacing: true,
    // jsx 标签的反尖括号需要换行
    jsxBracketSameLine: false,
    // 箭头函数,只有一个参数的时候,也需要括号
    arrowParens: 'always',
    // 每个文件格式化的范围是文件的全部内容
    rangeStart: 0,
    rangeEnd: Infinity,
    // 不需要写文件开头的 @prettier
    requirePragma: false,
    // 不需要自动在文件开头插入 @prettier
    insertPragma: false,
    // 使用默认的折行标准
    proseWrap: 'preserve',
    // 根据显示样式决定 html 要不要折行
    htmlWhitespaceSensitivity: 'css',
    // 换行符使用 lf
    endOfLine: 'lf',
}

Prettier 用来格式化代码,保持代码中分号,单双引号等等格式统一。

ESLint 主要用来校验 JavaScript 代码语法错误,也能起到规范代码格式的作用。

在日常开发中,我们既要使用 Prettier, 也要使用 ESLint 。用 ESLint 检查代码中可能存在的语法错误, 用 Prettier 调整代码格式

[t]sconfig.json

{
    "compilerOptions": {
        "baseUrl": "./",
        "paths": {
            "@/*": [
                "src/*"
            ],
            "__ROOT__/*": [
                "*"
            ]
        }
    },
    "exclude": [
        "node_modules"
    ]
}

配置编辑器按住 ctrl+鼠标滑到路径处,会自动提示到文件目录里面去

vite.config.js

具体配置请看官方文档https://cn.vitejs.dev/config/

export default defineConfig(({command, mode}) => {
    if (command === 'serve') {
        return {
            // dev 独有配置
        }
    } else {
        // command === 'build'
        return {
            // build 独有配置
        }
    }
})
907 次点击
所在节点    程序员
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/824308

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX