Vite-Vue3.x-TS-Eslint項目初始化(2022-05-02)

Vite-Vue3.x-TS-Eslint項目初始化

Lzq811/Vue3.x-vite-ts-eslint-prettier: vue3大屏基礎(chǔ)框架 (github.com)

1. init

yarn create vite demo-product --template vue-ts
cd ./demo-product
yarn
yarn dev
# 能正常方法 localhost:3000 頁面花吟,說明 init 成功

2. 使用 element-plus UI 庫

yarn add element-plus
  • 推薦使用 按需引入 文檔地址

    # 需要安裝下面兩個依賴
    yarn add unplugin-vue-component unplugin-auto-import
    
  • 然后再 vite.config.ts 文件中修改

    import { defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    import AutoImport from 'unplugin-auto-import/vite'
    import Component from 'unplugin-vue-components/vite'
    import {ElementPlusResolver } from 'unplugin-vue-components/resolvers'
    
    // https://vitejs.dev/config/
    export default defineConfig({
      plugins: [
        vue(),
        AutoImport({
          resolvers: [ElementPlusResolver()]
        }),
        Component({
          resolvers: [ElementPlusResolver()]
        })
      ]
    })
    
    
  • 然后在使用的組件中直接調(diào)用

    <el-button type="primary">hello element btn</el-button>
    
  • 自定義主題 文檔地址

  • 使用 Less

    # 安裝依賴
    yarn add less less-loader -D
    # 然后vite.config.js衅澈, 要require('path'), 如果require 和 __dirname報ts錯经备, 使用 @ts-ignore 或者安裝 @types/node 依賴
    css: {
        preprocessorOptions: {
          less: {
            modifyVars: {
              hack: `true; @import (reference) "${path.resolve(__dirname, 'src/assets/base.less')}"` // 全局定義的less文件
            },
            javascriptEnabled: true
          }
        }
      }
      
     # 在組件內(nèi)使用
     <style lang="less" scoped></style>
    

3. 使用 Eslint 部默、 Prettier 做代碼校驗和自動格式化

  • 安裝 eslint 以及相關(guān)依賴

    yarn add eslint eslint-plugin-vue vue-eslint-parser @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-config-airbnb-base eslint-plugin-import -D
    
  • vscode 編輯器 也要安裝 Eslint 和 Prettier 拓展

  • 根目錄添加 .eslintrc.js文件,并添加下面代碼

    module.exports = {
      root: true,
      globals: {
          defineEmits: 'readonly',
          defineProps: 'readonly'
      },
      extends: [
          'plugin:@typescript-eslint/recommended',
          'plugin:vue/vue3-recommended',
          'airbnb-base'
      ],
      parserOptions: {
          parser: '@typescript-eslint/parser',
          ecmaVersion: 2020
      },
      rules: {
          'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 禁用 debugger
          'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 禁用 console
          'no-bitwise': 'off', // 禁用按位運算符
          'no-tabs': 'off', // 禁用 tab
          'array-element-newline': ['error', 'consistent'], // 強制數(shù)組元素間出現(xiàn)換行
          indent: [
              'error',
              2,
              { MemberExpression: 0, SwitchCase: 1, ignoredNodes: ['TemplateLiteral'] }
          ], // 強制使用一致的縮進
          quotes: ['error', 'single'], // 強制使用一致的反勾號蘑志、雙引號或單引號
          'comma-dangle': ['error', 'always-multiline'], // 要求或禁止末尾逗號
          'object-curly-spacing': ['error', 'always'], // 強制在大括號中使用一致的空格
          'max-len': ['error', 120], // 強制一行的最大長度
          'no-new': 'off', // 禁止使用 new 以避免產(chǎn)生副作用
          'linebreak-style': 'off', // 強制使用一致的換行風格
          'import/extensions': 'off', // 確保在導入路徑中統(tǒng)一使用文件擴展名
          'eol-last': 'off', // 要求或禁止文件末尾存在空行
          'no-shadow': 'off', // 禁止變量聲明與外層作用域的變量同名
          'no-unused-vars': 'warn', // 禁止出現(xiàn)未使用過的變量
          'import/no-cycle': 'off', // 禁止一個模塊導入一個有依賴路徑的模塊回到自己身上
          'arrow-parens': 'off', // 要求箭頭函數(shù)的參數(shù)使用圓括號
          semi: ['error', 'never'], // 要求或禁止使用分號代替 ASI
          eqeqeq: 'on', // 要求使用 === 和 !==
          'no-param-reassign': 'off', // 禁止對 function 的參數(shù)進行重新賦值
          'import/prefer-default-export': 'off', // 如果模塊只輸入一個名字急但,則傾向于默認輸出
          'no-use-before-define': 'on', // 禁止在變量定義之前使用它們,則傾向于默認輸出
          'no-continue': 'off', // 禁用 continue 語句
          'prefer-destructuring': 'off', // 優(yōu)先使用數(shù)組和對象解構(gòu)
          'no-plusplus': 'off', // 禁用一元操作符 ++ 和 --
          'prefer-const': 'warn', // 要求使用 const 聲明那些聲明后不再被修改的變量
          'global-require': 'on', // 要求 require() 出現(xiàn)在頂層模塊作用域中
          'no-prototype-builtins': 'off', // 禁止直接調(diào)用 Object.prototypes 的內(nèi)置屬性
          'consistent-return': 'off', // 要求 return 語句要么總是指定返回的值波桩,要么不指定
          'one-var-declaration-per-line': 'off', // 要求或禁止在變量聲明周圍換行
          'one-var': 'off', // 強制函數(shù)中的變量要么一起聲明要么分開聲明
          'import/named': 'off', // 確保命名導入與遠程文件中的命名導出相對應(yīng)
          'object-curly-newline': 'off', // 強制大括號內(nèi)換行符的一致性
          'default-case': 'off', // 要求 switch 語句中有 default 分支
          'no-trailing-spaces': 'on', // 禁用行尾空格
          'func-names': 'off', // 要求或禁止使用命名的 function 表達式
          radix: 'off', // 強制在 parseInt() 使用基數(shù)參數(shù)
          'no-unused-expressions': 'off', // 禁止出現(xiàn)未使用過的表達式
          'no-underscore-dangle': 'off', // 禁止標識符中有懸空下劃線
          'no-nested-ternary': 'off', // 禁用嵌套的三元表達式
          'no-restricted-syntax': 'off', // 禁用特定的語法
          'no-await-in-loop': 'off', // 禁止在循環(huán)中出現(xiàn) await
          'import/no-extraneous-dependencies': 'off', // 禁止使用外部包
          'import/no-unresolved': 'off', // 確保導入指向一個可以解析的文件/模塊
          'template-curly-spacing': ['error', 'always'], // 要求或禁止模板字符串中的嵌入表達式周圍空格的使用
          '@typescript-eslint/no-var-requires': 'off', // 除import語句外镐躲,禁止使用require語句
          '@typescript-eslint/no-empty-function': 'off', // 不允許空函數(shù)
          '@typescript-eslint/no-explicit-any': 'off', // 禁止使用 any 類型
          'guard-for-in': 'off', // 要求 for-in 循環(huán)中有一個 if 語句
          'class-methods-use-this': 'off', // 強制類方法使用 this
          'vue/html-indent': ['error', 2], // 在<template>中強制一致縮進
          'vue/html-self-closing': 'off', // 執(zhí)行自閉合的風格
          'vue/max-attributes-per-line': [
              // 強制每行屬性的最大數(shù)量
              'warn',
              {
                  singleline: {
                      max: 3,
                      allowFirstLine: true
                  },
                  multiline: {
                      max: 1,
                      allowFirstLine: false
                  }
              }
          ],
          'vue/singleline-html-element-content-newline': 'off' // 要求單行元素的內(nèi)容前后有一個換行符
      }
    }
    
    
  • 根目錄添加 prettier.config.js文件,并添加下面代碼

    // prettier.config.js or .prettierrc.js
    module.exports = {
      // 一行最多 100 字符
      printWidth: 100,
      // 使用 2 個空格縮進
      tabWidth: 2,
      // 不使用縮進符撒穷,而使用空格
      useTabs: false,
      // 行尾需要有分號
      semi: false,
      // 使用單引號
      singleQuote: true,
      // 對象的 key 僅在必要時用引號
      quoteProps: 'as-needed',
      // jsx 不使用單引號裆熙,而使用雙引號
      jsxSingleQuote: false,
      // 末尾不需要逗號
      trailingComma: 'none',
      // 大括號內(nèi)的首尾需要空格
      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: 'lf'
    }
    
    
  • 根目錄 添加 .eslintignore 并寫入下面代碼

    /build/
    /config/
    /dist/
    /*.js
    /*.zip
    /*.rar
    
    

4. 配置環(huán)境變量

  • 在根目錄新建文件夾 env-config,然后在文件夾下新增文件并錄入內(nèi)容

    所有的環(huán)境變量必須以 VITE_ 開頭

    # 新增 .env 文件 寫入下面內(nèi)容
      VITE_ENV = DEV
      VITE_APP_BASE_URL = 'http://DEV.com'
      
    # 新增 .env.test 文件并寫入內(nèi)容
      VITE_ENV = TEST
      VITE_APP_BASE_URL = 'http://TEST.com'
      
    # 新增 .env.prod 文件并寫入內(nèi)容
      VITE_ENV = PROD
      VITE_APP_BASE_URL = 'http://PROD.com'
    
  • vite.config.js文件夾中配置 envDir

    // @ts-ignore 如果提示錯誤 使用 @ts-ignore 或者 yarn add @types/node 只有node里面才有 require 和 __dirname
    const path = require('path')
    function _resolve(dir) {
      // @ts-ignore
      return path.resolve(__dirname, dir)
    }
    
    // https://vitejs.dev/config/
    export default defineConfig({
      envDir: _resolve('env-config'),
      ...
    })
    
  • 修改 package.json 的命令(我比較喜歡用 start 代替 dev)

      "scripts": {
        "dev": "vite",
        "start": "vite --mode env",
        "start-test": "vite --mode test",
        "start-prod": "vite --mode prod",
        "build": "vue-tsc --noEmit && vite build",
        "build-test": "vue-tsc --noEmit && vite build --mode test",
        "build-prod": "vue-tsc --noEmit && vite build --mode prod",
        "preview": "vite preview"
      },
    
  • 使用 import.meta.env 來獲取環(huán)境變量信息

    # 組件里面調(diào)用測試
    onMounted(() => {console.log(import.meta.env)})
    
  • 執(zhí)行start命令

    yarn start # 執(zhí)行 dev 環(huán)境
    # OR
    yarn start-test # 執(zhí)行 test 環(huán)境
    # OR
    yarn start-prod # 執(zhí)行 orod 環(huán)境
    
    #demo
    yarn start-test
    # 調(diào)取 import.meta.env 的結(jié)果
      BASE_URL: "/"
      DEV: true
      MODE: "test"
      PROD: false
      VITE_APP_BASE_URL: "http://TEST.com"
      VITE_ENV: "TEST"
    
  • 執(zhí)行build命令

    #demo
    yarn build-test
    # 調(diào)取 import.meta.env 的結(jié)果
      BASE_URL: "/"
      DEV: true
      MODE: "test"
      PROD: false
      VITE_APP_BASE_URL: "http://TEST.com"
      VITE_ENV: "TEST"
    

5. 使用 axios 封裝 ajax 請求

  • 安裝 axios

    yarn add axios
    
  • 配置封裝

    1. 新建文件src/api/index.tsx
    // index.tsx 文件
    import ajax from './ajax'
    /*
     * ajax 從 ajax.js 引入 需要
     * 第一個 參數(shù) 是 url 必填
     * 第二個 參數(shù) 是 params對象 默認 {} 非必填
     * 第三個 參數(shù) 是 GET、POST 請求方式蚀同, 默認 POST, 非必填
     */
    // 后臺地址
    const BASE_URL: string = import.meta.env.VITE_APP_BASE_URL || '' // 環(huán)境變量后臺地址
    // const BASE_URL: string = `http:xxxx/api`
    // const BASE_URL_OTHER:string = `http:xxx2.api` // 多個后臺地址
    
    interface IParams {}
    
    // 登陸接口
    export const ReqLogin = (params: IParams) => ajax(`${BASE_URL}login`, params, 'POST') // POST 是默認值拷恨,可以不寫
    
    // export const ReqOther = (params:IParams) => ajax(`${BASE_URL_OTHER}login`, params)
    
    
  1. 新建文件 src/api/ajax.tsx

    // ajax.tsx 文件
    import axios from 'axios'
    
    // 可以在這里做一下請求攔截谢肾,設(shè)置公共請求頭等
    
    export default function ajax(url: string, data: any = {}, type: string = 'POST') {
      // 判斷 url 地址小泉, 在多個后臺地址時候使用, 可以在這里攔截使用不同的請求頭微姊,傳入不同token等操作
    
      return new Promise((resolve, reject) => {
        let promise: any // 返回一個 promise 對象
        if (type === 'GET') {
          promise = axios.get(url, { params: data })
    
          // 多個后臺地址時候兢交,傳入不同的token值
          promise = axios.get(url, {
            params: data,
            headers: { access_totken: sessionStorage.getItem('token_other') || '' }
          })
        } else if (type === 'POST') {
          promise = axios.post(url, data)
    
          // 多個后臺地址時候,傳入不同的token值
          promise = axios.get(url, data)
        }
        // 統(tǒng)一處理 response
        promise
          .then((response: any) => {
            response && response.data ? resolve(response.data) : reject(response)
          })
          .catch((error: any) => {
            console.log(error)
          })
      })
    }
    
    
  2. 組件內(nèi)調(diào)用

 ```tsx
 import {ReqLogin} from './src/api'
 
 const ajaxDemo = async () => {
    const res:any = await ReqLogin({}) // res就是ajax返回的結(jié)果
 }
 ```

6. 頁面彈性布局

  • 新建 src/utils/comfort_page.tsx

    /*
     * 做頁面自適應(yīng)
     * 0. 項目跟元素 id = root
     * 1. width 為適應(yīng)基準
     * 2. 無論 width height 如何變化,都要輸出 16 / 9 比例的頁面
     * 3. 客戶的設(shè)備分辨率 1920 * 1080
     */
    
    // @ts-nocheck
    
    const W = 1920
    const H = 1080
    
    export default () => {
      const root = document.getElementById('root')?.style
      window.onresize = () => {
        root.transform = `scale(${document.body.offsetWidth / W})`
        root.transformOrigin = `left top 0px`
        root.width = `${W}px`
        root.height = `${H}px`
      }
      root.transform = `scale(${document.body.offsetWidth / W})`
      root.transformOrigin = `left top 0px`
      root.width = `${W}px`
      root.height = `${H}px`
    }
    
    
  • App.vue 組件引入

    import ComfortPage from './utils/comfort_page'
    onMounted(() => {
      ComfortPage()
    })
    

7. 路由

  • 路由要用 4 版本的凳干,才對應(yīng) vue3版本

    yarn add vue-router@4
    
  • 新增 src/routes/index.tsx

    import { createRouter, createWebHistory } from 'vue-router'
    
    const routes: any = [
      {
        path: '/',
        redirect: 'home'
      },
      {
        path: '/home',
        name: 'home',
        component: () => import('../Home.vue') // 要提前注冊號該組件
      },
      {
        path: '/first',
        name: 'first',
        component: () => import('../First.vue') // 要提前注冊號該組件
      }
    ]
    
    const router = createRouter({
      history: createWebHistory(),
      routes: routes
    })
    
    router.beforeEach((to, from) => {
      const { path: toPath } = to
      const { path: fromPath } = from
      if (toPath === fromPath) {
        return false
      }
    })
    
    export default router
    
    
  • 修改 main.ts 文件

    import router from './routes'
    
    const app = createApp(App)
    app.use(router)
    app.mount('#app')
    
  • 修改 App.vue 文件

    <template>
        <router-view></router-view>
    </template>
    
  • 跳轉(zhuǎn)

    import {useRouter} from 'vue-router'
    
    const router = useRouter()
    
    router.push('./first')
    

8. 路徑別名

  • 修改 vite.config.js 內(nèi)容

    export default defineConfig({
      envDir: path.resolve(__dirname, 'env-config'),
      plugins: [
        vue(),
        AutoImport({
          resolvers: [ElementPlusResolver()]
        }),
        Component({
          resolvers: [ElementPlusResolver()]
        })
      ],
      css: {
        preprocessorOptions: {
          less: {
            modifyVars: {
              hack: `true; @import (reference) "${path.resolve(__dirname, 'src/assets/base.less')}"` // 全局定義的less文件
            },
            javascriptEnabled: true
          }
        }
      },
      resolve: {
        extensions: ['.js', '.vue', '.json'],
        alias: {
          '@api': _resolve('src/api'),
          '@components': _resolve('src/components'),
          '@': _resolve('src')
        }
      }
    })
    
  • 新增 src/ts.extends.json 文件

    {
      "compilerOptions": {
        "baseUrl": ".",
        "paths": {
          "@/*": [
            "*"
          ],
          "@api/*": [
            "src/api/*"
          ]
        }
      }
    }
    
  • 修改 tsconfig.json 文件

    {
      ...
      "extends": "./ts.extends.json" # 添加該屬性
    }
    
  • 使用

    import { ReqLogin } from '@api/index'
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市只磷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌预厌,老刑警劉巖畏陕,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異犹芹,居然都是意外死亡,警方通過查閱死者的電腦和手機腰埂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門蜈膨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人驴一,你說我怎么就攤上這事灶壶。” “怎么了驰凛?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長趣钱。 經(jīng)常有香客問我胚宦,道長燕垃,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任利术,我火速辦了婚禮低矮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘轮蜕。我一直安慰自己蝗锥,他們只是感情好跃洛,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布汇竭。 她就那樣靜靜地躺著穴张,像睡著了一般。 火紅的嫁衣襯著肌膚如雪皂甘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天璧瞬,我揣著相機與錄音渐夸,去河邊找鬼。 笑死墓塌,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的桃纯。 我是一名探鬼主播披坏,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼棒拂,長吁一口氣:“原來是場噩夢啊……” “哼伞梯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起漾峡,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤喻旷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后且预,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡遍尺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年乾戏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鼓择。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡就漾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出从藤,到底是詐尸還是另有隱情,我是刑警寧澤懊蒸,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布悯搔,位于F島的核電站,受9級特大地震影響妒貌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜菊碟,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一在刺、第九天 我趴在偏房一處隱蔽的房頂上張望头镊。 院中可真熱鬧,春花似錦魄幕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽靡馁。三九已至机久,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間膘盖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工结缚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人红竭。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓喘落,卻偏偏與公主長得像,于是被迫代替她去往敵國和親瘦棋。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

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