? ? ? 站在Vue3上-構建管理系統vue-vite-admin-ts

vipbic發表於2021-12-29
出發點的本質是想學習下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

專案預覽

?????線上預覽

vue-vite-admin-ts

構建佈局

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')
})
  • mitt 是全域性通訊就是取代Vue2的EventBus,是一個體積極小的第三方訊息釋出/訂閱式JavaScript庫 官方文件是與框架無關的,所以這個React、Vue都可以用

最終佈局檔案請看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>
<script lang="ts">
import {defineComponent, computed} from 'vue';
import Slider from './slider.vue'
import HeaderTop from './headerTop.vue'
import HeaderProcess from './headerProcess.vue'
import LayoutContainer from './layoutContainer.vue'
import {themeHook} from '@/packages/hook'
import {useStore} from "vuex";

export default defineComponent({
    components: {
        Slider,
        HeaderTop,
        HeaderProcess,
        LayoutContainer
    },
    setup() {
        const {layoutClassName} = themeHook()
        const store = useStore();
        const marginLeft = computed(() => store.state.app.themeConfig.menuMaxWidth + 'px')
        return {
            layoutClassName,
            marginLeft
        }
    }
});
</script>

路由介紹

Vue Router4 是 Vue.js 的官方路由。它與 Vue.js 核心深度整合,讓用 Vue.js 構建單頁應用變得輕而易舉。功能包括:

  • 巢狀路由對映
  • 動態路由選擇
  • 模組化、基於元件的路由配置
  • 路由引數、查詢、萬用字元
  • 展示由 Vue.js 的過渡系統提供的過渡效果
  • 細緻的導航控制
  • 自動啟用 CSS 類的連結
  • HTML5 history 模式或 hash 模式
  • 可定製的滾動行為
  • URL 的正確編碼

具體檔案請看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 中,

  • 從瀏覽器中建立 XMLHttpRequests
  • 從 node.js 建立 http 請求
  • 支援 Promise API
  • 攔截請求和響應
  • 轉換請求資料和響應資料
  • 取消請求
  • 自動轉換 JSON 資料
  • 客戶端支援防禦 XSRF

此處程式碼還應有響應攔截,請求攔截,沒有貼上出來,具體請看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因為兩個重要的特性風靡前端:

  • 資料型別豐富 :支援生成隨機的文字、數字、布林值、日期、郵箱、連結、圖片、顏色等。
  • 攔截Ajax請求 :不需要修改既有程式碼,就可以攔截 Ajax 請求,返回模擬的響應資料。安全又便捷
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 工具,

  • JSLint
  • JSHint
  • ESLint

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 獨有配置
        }
    }
})

完成的功能

✅ 使用Vue 3

✅ 使用Vuex 4.x

✅ 使用Vue-router 4.x

✅ 基於Vite 2.6

✅ 基於Ant Design Vue

✅ 整體框架響應式佈局

✅ 專案切換

✅ 使用者登入攔截,使用者退出

✅ 麵包屑導航 + 多種佈局效果

✅ 基於後臺許可權,按鈕許可權設計

✅ 選單導航 + 多種佈局

✅ 內建iconfont字型圖示,自動生成元件

✅ 基於axios封裝post,get,all,upload,download

✅ http錯誤重連

✅ 元件許可權指令封裝

✅ tsx構建全域性元件

✅ http網路元件(vue3新特性)

✅ 選單管理,包含增、刪、改、查,選單是快取、是否固定、是否隱藏(但展示)、是否隱藏等待 具體功能,檢視文件

✅ 包含富文字編輯器,檔案列印,圖表預覽,動畫元件,狀態詳情元件等等

✅ 支援多頁面應用

✅ 支援iframe內嵌

✅ 頁面重新整理

✅ 頁面全屏

✅ 右鍵選單封裝

✅ 滾動條優化

✅ 骨架屏元件預覽

✅ 基於封裝loadsh深層遍歷、查詢、無規律查詢

✅ 基於mitt全域性通訊

✅ 基於vxe-table解決萬量級表格渲染

✅ Mock資料

✅ Egg.js後端服務,具體操作看文件

✅ sequelize模型增刪改查

✅ Eslint程式碼檢查

✅ 開發編輯器全域性配置

✅ 打包壓縮處理Gzip

相關文章