vue3+ts+vite+pinia+element plus 從零打造一個前端后臺管理項目

本文是對前一段時間自學vue最新語法的一個總結(jié),因為過去的時間已經(jīng)一個多月了稿存,所以盡可能的還原當時的一步步過程和中間遇到的問題瞳秽,作為一個總結(jié)日后查看。

通過這個文章练俐,可以了解到

  • 如何使用使用 Vite 搭建項目
  • 如何在 Vite 中集成 typescript并使用
  • 如何在 Vite 中集成 vue-router4 和 pinia并使用
  • 如何使用 vue3 的伴侶 vueuse
  • 如何在項目中集成 eslint 和 prettier 保證代碼質(zhì)量
  • 如何規(guī)范化 git 提交信息
  • 如何為團隊開發(fā)專屬的項目模板
  • element-ui的使用
  • 如何封裝一個axios網(wǎng)絡(luò)類
  • 如何導(dǎo)入svg圖庫、使用全局變量等具體操作

下面我們就開始步入正題

一燕锥、初始化項目

按步驟進行初始化:

根據(jù)官網(wǎng),直接輸入命令

npm init vue@latest

這一指令將會安裝并執(zhí)行 create-vue归形,它是 Vue 官方的項目腳手架工具鼻由。你將會看到一些諸如 TypeScript 和測試支持之類的可選功能提示:

image.png

然后我們根據(jù)提示,進行以下操作:

  cd vue-system
  npm install
  npm run lint
  npm run dev

這樣我們的vue3就順利的跑起來了蔼紧,頁面如下:


WX20230215-155122@2x.png

運行項目不會默認打開瀏覽器,需要在package.json里面 ,在vite 后面加上--open


w
集成配置

1狠轻、使用別名@/,安裝types/node來加載path模塊

npm i @types/node --save-dev

2哈误、修改tsconfig.json

{
  "extends": "@vue/tsconfig/tsconfig.web.json",
  "include": ["env.d.ts", "src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "compilerOptions": {
    "typeRoots": [
      "node_modules/@types", // 默認值
      "src/types"
   ],
    "target": "esnext",
    "useDefineForClassFields": true,
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "lib": ["esnext", "dom"],
    "baseUrl": "./",
    "paths":{
      "@": ["src"],
      "@/*": ["src/*"],
    }
  },
  "references": [
    {
      "path": "./tsconfig.config.json"
    }
  ]
}

3蜜自、修改 vite.config.ts

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import * as path from 'path';

// https://vitejs.dev/config/
export default defineConfig({
    resolve: {
        //設(shè)置別名
        alias: {
            '@': path.resolve(__dirname, 'src')
        }
    },
    plugins: [vue()],
    server: {
        port: 8080, //啟動端口
        hmr: {
            host: '127.0.0.1',
            port: 8080
        },
        // 設(shè)置 https 代理
        proxy: {
            '/api': {
                target: 'your https address',
                changeOrigin: true,
                rewrite: (path: string) => path.replace(/^\/api/, '')
            }
        }
    }
});

二、代碼質(zhì)量風格的統(tǒng)一

ESLint

這個在項目初始化已經(jīng)安裝了重荠,后面看看需要什么更詳細的配置。

prettier

代碼格式化的工具仇参,具體配置步驟如下:
1、首先在VS Code中安裝Prettier - Code formatter插件
![image.png](https://upload-images.jianshu.io/upload_images/246657-f2cbf3a9e10e1d5e.png?imageMogr2/auto-orient/strip%7CimageView2/2 /w/1240)
2诈乒、然后在設(shè)置中進行勾選

image.png

3、在代碼文件中右鍵喂饥,選擇 使用...格式化文件
image.png

4肠鲫、配置默認格式化程序
image.png

5、在項目種的.prettierrc.json文件中

{
  // 一行最多 80 字符
  "printWidth": 80,
  // 使用 2 個空格縮進
  "tabWidth": 2,
  // 不使用 tab 縮進捞高,而使用空格
  "useTabs": false,
  // 行尾需要有分號
  "semi": false,
  // 使用單引號代替雙引號
  "singleQuote": true,
  // 對象的 key 僅在必要時用引號
  "quoteProps": "as-needed",
  // jsx 不使用單引號,而使用雙引號
  "jsxSingleQuote": false,
  // 末尾使用逗號
  "trailingComma": "all",
  // 大括號內(nèi)的首尾需要空格 { foo: bar }
  "bracketSpacing": true,
  // jsx 標簽的反尖括號需要換行
  "jsxBracketSameLine": false,
  // 箭頭函數(shù)棠枉,只有一個參數(shù)的時候泡挺,也需要括號
  "arrowParens": "always",
  // 每個文件格式化的范圍是文件的全部內(nèi)容
  "rangeStart": 0,
  "rangeEnd": Infinity,
  // 不需要寫文件開頭的 @prettier
  "requirePragma": false,
  // 不需要自動在文件開頭插入 @prettier
  "insertPragma": false,
  // 使用默認的折行標準
  "proseWrap": "preserve",
  // 根據(jù)顯示樣式?jīng)Q定 html 要不要折行
  "htmlWhitespaceSensitivity": "css",
  // 換行符使用 lf
  "endOfLine": "auto"
}

json文件中不能注釋命浴,所以要把注釋去掉

{
  "printWidth": 80,
  "tabWidth": 2,
  "useTabs": false,
  "semi": false,
  "singleQuote": true,
  "quoteProps": "as-needed",
  "jsxSingleQuote": false,
  "trailingComma": "all",
  "bracketSpacing": true,
  "jsxBracketSameLine": false,
  "arrowParens": "always",
  "requirePragma": false,
  "insertPragma": false,
  "proseWrap": "preserve",
  "htmlWhitespaceSensitivity": "css",
  "endOfLine": "auto"
}

再修改代碼保存的時候,就可以了

三媳溺、提交規(guī)范

為了使團隊多人協(xié)作更加的規(guī)范,所以需要每次在 git 提交的時候悬蔽,做一次硬性規(guī)范提交,規(guī)范 git 的提交信息蝎困,具體提交規(guī)范可參考:
http://www.reibang.com/p/635670ad2fca

一倍啥、使用 commitizen 規(guī)范git提交(交互式提交 + 自定義提示文案 + Commit規(guī)范)

這里是指用代碼行命令的時候,設(shè)置可視化的提示虽缕,步驟如下:

1、安裝

npm install -D commitizen cz-conventional-changelog @commitlint/config-conventional @commitlint/cli commitlint-config-cz cz-customizable

2、配置 package.json

{
  ...
  "scripts": {
    "commit:comment": "引導(dǎo)設(shè)置規(guī)范化的提交信息",
    "commit":"git-cz",
  },

  "config": {
      "commitizen": {
        "path": "node_modules/cz-customizable"
      }
  },
}

3江耀、添加文件 commitlint.config.js

module.exports = {
    extends: ['@commitlint/config-conventional', 'cz'],
    rules: {
        'type-enum': [
            2,
            'always',
            [
                'feature', // 新功能(feature)
                'bug', // 此項特別針對bug號诉植,用于向測試反饋bug列表的bug修改情況
                'fix', // 修補bug
                'ui', // 更新 ui
                'docs', // 文檔(documentation)
                'style', // 格式(不影響代碼運行的變動)
                'perf', // 性能優(yōu)化
                'release', // 發(fā)布
                'deploy', // 部署
                'refactor', // 重構(gòu)(即不是新增功能,也不是修改bug的代碼變動)
                'test', // 增加測試
                'chore', // 構(gòu)建過程或輔助工具的變動
                'revert', // feat(pencil): add ‘graphiteWidth’ option (撤銷之前的commit)
                'merge', // 合并分支系宫, 例如: merge(前端頁面): feature-xxxx修改線程地址
                'build', // 打包
            ],
        ],
        // <type> 格式 小寫
        'type-case': [2, 'always', 'lower-case'],
        // <type> 不能為空
        'type-empty': [2, 'never'],
        // <scope> 范圍不能為空
        'scope-empty': [2, 'never'],
        // <scope> 范圍格式
        'scope-case': [0],
        // <subject> 主要 message 不能為空
        'subject-empty': [2, 'never'],
        // <subject> 以什么為結(jié)束標志建车,禁用
        'subject-full-stop': [0, 'never'],
        // <subject> 格式,禁用
        'subject-case': [0, 'never'],
        // <body> 以空行開頭
        'body-leading-blank': [1, 'always'],
        'header-max-length': [0, 'always', 72],
    },
};

4缤至、新增自定義提示文件 .cz-config.js

module.exports = {
    types: [
        {value: 'feature',  name: 'feature:  增加新功能'},
        {value: 'bug',      name: 'bug:      測試反饋bug列表中的bug號'},
        {value: 'fix',      name: 'fix:      修復(fù)bug'},
        {value: 'ui',       name: 'ui:       更新UI'},
        {value: 'docs',     name: 'docs:     文檔變更'},
        {value: 'style',    name: 'style:    代碼格式(不影響代碼運行的變動)'},
        {value: 'perf',     name: 'perf:     性能優(yōu)化'},
        {value: 'refactor', name: 'refactor: 重構(gòu)(既不是增加feature,也不是修復(fù)bug)'},
    {value: 'release',  name: 'release:  發(fā)布'},
    {value: 'deploy',   name: 'deploy:   部署'},
        {value: 'test',     name: 'test:     增加測試'},
        {value: 'chore',    name: 'chore:    構(gòu)建過程或輔助工具的變動(更改配置文件)'},
        {value: 'revert',   name: 'revert:   回退'},
        {value: 'build',    name: 'build:    打包'}
    ],
    // override the messages, defaults are as follows
    messages: {
        type: '請選擇提交類型:',
        customScope: '請輸入您修改的范圍(可選):',
        subject: '請簡要描述提交 message (必填):',
        body: '請輸入詳細描述(可選嫉到,待優(yōu)化去除,跳過即可):',
        footer: '請輸入要關(guān)閉的issue(待優(yōu)化去除何恶,跳過即可):',
        confirmCommit: '確認使用以上信息提交嚼黔?(y/n/e/h)'
    },
    allowCustomScopes: true,
    skipQuestions: ['body', 'footer'],
    subjectLimit: 72
};

6、終端輸入git add .
7唬涧、接著輸入npm run commit


image.png

image.png
二、VS Code插件

使用git-commint-plugin插件
具體使用可以查看這篇文章:
https://blog.csdn.net/weixin_41056807/article/details/127202536

三捧搞、sourcetree使用

使用腳本來做sourcetree的提交規(guī)范
具體使用可以查看這篇文章:
http://www.reibang.com/p/dc65bd37972a
生效后souretree的樣子如下圖

image.png

四狮荔、集成ElementPlus

1、集成
npm install element-plus --save

在main.ts中配置

import { createApp } from 'vue'
import { createPinia } from 'pinia'

import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

import './assets/main.css'

const app = createApp(App)
//Pinia
app.use(createPinia())
app.use(router)
app.use(ElementPlus)

app.mount('#app')

如果您使用 Volar殖氏,請在 tsconfig.json 中通過 compilerOptions.type 指定全局組件類型。

// tsconfig.json
{
  "compilerOptions": {
    // ...
    "types": ["element-plus/global"]
  }
}

五受葛、項目編寫以及過程中的內(nèi)容知識整理

1偎谁、刪除App.vue中多余的內(nèi)容

<script setup lang="ts">
import { RouterView } from 'vue-router'
</script>

<template>
  <RouterView />
</template>

<style scoped></style>

2纲堵、刪除多余文件,添加login頁面文件
刪除views文件夾下自帶的文件铐望,添加login頁面,并在router.ts中配置一下路由


image.png

image.png

3正蛙、引入全局樣式文件


image.png

main.ts中引入
import '@/assets/styles/index.scss' // global css

4营曼、login靜態(tài)頁面編寫

  • 首先代碼如下:
<template>
  <div class="login-container">
    <el-form
      ref="ruleFormRef"
      :model="loginForm"
      class="login-form"
      :rules="rules"
    >
      <div class="title-container">
        <h3 class="title">用戶登錄</h3>
      </div>
      <!-- 賬號 -->
      <el-form-item prop="username">
        <!-- <svg-icon
          class="svg-container"
          iconName="user"
          iconSize="20"
        ></svg-icon> -->
        <el-input v-model="loginForm.username"></el-input>
      </el-form-item>
      <!-- 密碼 -->
      <el-form-item prop="password">
        <!-- <svg-icon
          class="svg-container"
          iconName="password"
          iconSize="20"
        ></svg-icon> -->
        <el-input
          v-model="loginForm.password"
          type="password"
          showPassword
        ></el-input>
      </el-form-item>
      <!-- 登錄按鈕 -->
      <el-button
        type="primary"
        class="login-button"
        @click="handleLogin(ruleFormRef)"
      >
        登錄
      </el-button>
    </el-form>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'

const loginForm = ref({
  username: 'admin',
  password: '123456',
})

const ruleFormRef = ref<FormInstance>()

const rules = reactive<FormRules>({
  username: [
    { required: true, message: 'Please input Activity name', trigger: 'blur' },
  ],
  password: [
    { required: true, message: 'Please input password', trigger: 'blur' },
  ],
})
// 登錄點擊
const handleLogin = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  console.log('click login button')
}
</script>

<style lang="scss" scoped>
$bg: #2d3a4b;
$dark_gray: #889aa4;
$light_gray: #eee;
$cursor: #fff;

.login-container {
  width: 100vw;
  height: 100vh;
  background-color: $bg;
  display: flex;
  align-items: center;
  justify-content: center;

  .login-form {
    width: 520px;
    overflow: hidden;
    display: flex;
    flex-direction: column;

    :deep(.el-form-item) {
      border: 1px solid rgba(255, 255, 255, 0.1);
      background: white;
      border-radius: 5px;
    }

    :deep(.el-input) {
      height: 47px;
      width: 92%;
      padding: 12px 5px;
      color: #000;
      height: 47px;

      .el-input__wrapper {
        background: transparent;
        box-shadow: none;
      }
    }
    .login-button {
      width: 50%;
      height: 40px;
      margin: 0 auto;
    }
  }
  .title-container {
    .title {
      color: $light_gray;
      font-size: 26px;
      font-weight: bold;
      text-align: center;
      margin-bottom: 20px;
    }
  }

  .svg-container {
    padding: 6px 5px 6px 15px;
    color: $dark_gray;
    vertical-align: middle;
    display: inline-block;
  }
}
</style>
  • 在css的編寫中我們引入了scss蒂阱,此時運行項目報錯vite] Internal server error: Preprocessor dependency "sass" not found. Did you install it? Plugin: vite:css
    我們需要來安裝他,這樣就不報錯了
    npm install sass --save-dev

  • 這里來看一下scss和sass的介紹
    https://blog.csdn.net/qq_45947664/article/details/127857374

  • 這里還用:deep(.el-input)來修改input的默認樣式鳄厌,而不用::v-deep了

這樣我們就完成了靜態(tài)頁面的編寫,效果如下


image.png

5了嚎、ref和reactive的異同
這里我們用到了import { ref, reactive } from 'vue',來講一下二者的異同歪泳,直接貼結(jié)論:

相同點:創(chuàng)建響應(yīng)式對象

不同點:

  • ref可接受對象類型也可以接受基本類型即所有類型赘风,而reactive只能接收Array、Object邀窃、Map、Set這種引用類型
  • ref創(chuàng)建的數(shù)據(jù)返回類型為RefImpl 瞬捕,而RefImpl._value是一個 reactive 代理的原始對象舵抹,reactive創(chuàng)建的數(shù)據(jù)返回類型為Proxy
  • ref使用.value來取值和賦值

參考:https://www.bilibili.com/read/cv18429108

6、svg圖標的使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末惧蛹,一起剝皮案震驚了整個濱河市刑枝,隨后出現(xiàn)的幾起案子迅腔,更是在濱河造成了極大的恐慌,老刑警劉巖沧烈,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異锌雀,居然都是意外死亡,警方通過查閱死者的電腦和手機腋逆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來闲礼,“玉大人,你說我怎么就攤上這事柬泽。” “怎么了锨并?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長第煮。 經(jīng)常有香客問我,道長包警,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任害晦,我火速辦了婚禮,結(jié)果婚禮上壹瘟,老公的妹妹穿的比我還像新娘。我一直安慰自己稻轨,他們只是感情好,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布政冻。 她就那樣靜靜地躺著枚抵,像睡著了一般赠幕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上榕堰,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天,我揣著相機與錄音逆屡,去河邊找鬼。 笑死魏蔗,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的莺治。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼谣旁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了榄审?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤浪感,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后饼问,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡峻堰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了茧妒。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片萧吠。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖纸型,靈堂內(nèi)的尸體忽然破棺而出梅忌,到底是詐尸還是另有隱情除破,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布瑰枫,位于F島的核電站,受9級特大地震影響光坝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜盯另,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鸳惯。 院中可真熱鬧,春花似錦芝发、人聲如沸绪商。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽理张。三九已至,卻和暖如春绵患,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背落蝙。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留筏勒,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓管行,卻偏偏與公主長得像,于是被迫代替她去往敵國和親捐顷。 傳聞我的和親對象是個殘疾皇子雨效,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容