飞道的博客

Vue3 全家桶 + Element Plus + Vite + TypeScript + Eslint 项目配置最佳实践

1056人阅读  评论(0)

尤大的 Vue3.0 已经发布有一阵子了,已经很成熟了。

而且 Element Plus + Vite 也出了一段时间了,是时候该上手体验分享一波了。

主要是要熟练一下 Vue3,好准备用 Vue3 重构一下自己的网站项目: blog-vue-typescript ,计划是过年期间会着手重构这个项目,年后会上线。

1. 初化化项目

全局安装 vite-app

npm i -g vite-app

创建项目


   
  1. yarn create vite-app <project-name>
  2. # 或者
  3. npm init vite-app <project-name>

进入项目,安装依赖


   
  1. cd <project-name>
  2. yarn # 或 npm i

运行项目

yarn dev 

打开浏览器 http://localhost:3000 查看

2. 引入TypeScript

加入 ts 依赖

yarn add --dev typescript

在 项目根目录下创建 TypeScript 的配置文件 tsconfig.json


   
  1. {
  2.    "compilerOptions": {
  3.      // 允许从没有设置默认导出的模块中默认导入。这并不影响代码的输出,仅为了类型检查。
  4.      "allowSyntheticDefaultImports"true,
  5.     
  6.      // 解析非相对模块名的基准目录
  7.      "baseUrl"".",
  8.      "esModuleInterop"true,
  9.      // 从 tslib 导入辅助工具函数(比如 __extends, __rest等)
  10.      "importHelpers"true,
  11.      // 指定生成哪个模块系统代码
  12.      "module""esnext",
  13.      // 决定如何处理模块。
  14.      "moduleResolution""node",
  15.      // 启用所有严格类型检查选项。
  16.      // 启用 --strict相当于启用 --noImplicitAny, --noImplicitThis, --alwaysStrict, 
  17.      // --strictNullChecks和 --strictFunctionTypes和--strictPropertyInitialization。
  18.      "strict"true,
  19.      // 生成相应的 .map文件。
  20.      "sourceMap"true,
  21.      // 忽略所有的声明文件( *.d.ts)的类型检查。
  22.      "skipLibCheck"true,
  23.      // 指定ECMAScript目标版本 
  24.      "target""esnext",
  25.     
  26.      // 要包含的类型声明文件名列表
  27.      "types": [
  28.     ],
  29.      "isolatedModules"true,
  30.      // 模块名到基于 baseUrl的路径映射的列表。
  31.      "paths": {
  32.        "@/*": [
  33.          "src/*"
  34.       ]
  35.     },
  36.      // 编译过程中需要引入的库文件的列表。
  37.      "lib": [
  38.        "ESNext",
  39.        "DOM",
  40.        "DOM.Iterable",
  41.        "ScriptHost"
  42.     ]
  43.   },
  44.    "include": [
  45.      "src/**/*.ts",
  46.      "src/**/*.tsx",
  47.      "src/**/*.vue",
  48.      "tests/**/*.ts",
  49.      "tests/**/*.tsx"
  50.   ],
  51.    "exclude": [
  52.      "node_modules"
  53.   ]
  54. }

在 src 目录下新加 shim.d.ts 文件


   
  1. /* eslint-disable */
  2. import  type { DefineComponent } from  'vue'
  3. declare module  '*.vue' {
  4.    const component: DefineComponent<{}, {}, any>
  5.   export  default component
  6. }

把 main.js 修改成 main.ts

在根目录,打开 Index.html


   
  1. <script  type= "module" src= "/src/main.js"></script>
  2. 修改为:
  3. <script  type= "module" src= "/src/main.ts"></script>

3. 引入 eslint

安装 eslint prettier 依赖

@typescript-eslint/parser @typescr ipt-eslint/eslint-plugin 为 eslint 对 typescript 支持。

yarn add --dev eslint prettier eslint-config-prettier eslint-plugin-prettier eslint-plugin-vue @typescript-eslint/parser @typescr ipt-eslint/eslint-plugin

在根目录下建立 eslint 配置文件:.eslintrc.js


   
  1. module.exports = {
  2.   parser:  'vue-eslint-parser',
  3.   parserOptions: {
  4.     parser:  '@typescript-eslint/parser',
  5.     ecmaVersion:  2020,
  6.     sourceType:  'module',
  7.     ecmaFeatures: {
  8.       jsx:  true
  9.     }
  10.   },
  11.   extends: [
  12.      'plugin:vue/vue3-recommended',
  13.      'plugin:@typescript-eslint/recommended',
  14.      'prettier/@typescript-eslint',
  15.      'plugin:prettier/recommended'
  16.   ],
  17.   rules: {
  18.      '@typescript-eslint/ban-ts-ignore''off',
  19.      '@typescript-eslint/explicit-function-return-type''off',
  20.      '@typescript-eslint/no-explicit-any''off',
  21.      '@typescript-eslint/no-var-requires''off',
  22.      '@typescript-eslint/no-empty-function''off',
  23.      'vue/custom-event-name-casing''off',
  24.      'no-use-before-define''off',
  25.      // 'no-use-before-define': [
  26.      //   'error',
  27.      //   {
  28.      //     functions: false,
  29.      //     classes: true,
  30.      //   },
  31.      // ],
  32.      '@typescript-eslint/no-use-before-define''off',
  33.      // '@typescript-eslint/no-use-before-define': [
  34.      //   'error',
  35.      //   {
  36.      //     functions: false,
  37.      //     classes: true,
  38.      //   },
  39.      // ],
  40.      '@typescript-eslint/ban-ts-comment''off',
  41.      '@typescript-eslint/ban-types''off',
  42.      '@typescript-eslint/no-non-null-assertion''off',
  43.      '@typescript-eslint/explicit-module-boundary-types''off',
  44.      '@typescript-eslint/no-unused-vars': [
  45.        'error',
  46.       {
  47.         argsIgnorePattern:  '^h$',
  48.         varsIgnorePattern:  '^h$'
  49.       }
  50.     ],
  51.      'no-unused-vars': [
  52.        'error',
  53.       {
  54.         argsIgnorePattern:  '^h$',
  55.         varsIgnorePattern:  '^h$'
  56.       }
  57.     ],
  58.      'space-before-function-paren''off',
  59.     quotes: [ 'error''single'],
  60.      'comma-dangle': [ 'error''never']
  61.   }
  62. };

建立 prettier.config.js


   
  1. module.exports = {
  2.   printWidth:  100,
  3.   tabWidth:  2,
  4.   useTabs:  false,
  5.   semi:  false// 未尾逗号
  6.   vueIndentScriptAndStyle:  true,
  7.   singleQuote:  true// 单引号
  8.   quoteProps:  'as-needed',
  9.   bracketSpacing:  true,
  10.   trailingComma:  'none'// 未尾分号
  11.   jsxBracketSameLine:  false,
  12.   jsxSingleQuote:  false,
  13.   arrowParens:  'always',
  14.   insertPragma:  false,
  15.   requirePragma:  false,
  16.   proseWrap:  'never',
  17.   htmlWhitespaceSensitivity:  'strict',
  18.   endOfLine:  'lf'
  19. }

4. vue-router、vuex

yarn add vue-router@next vuex@next

4.1 vuex

在根目录下创建 store/index.ts


   
  1. import { InjectionKey } from  'vue'
  2. import { createStore, Store } from  'vuex'
  3. export  interface State {
  4.   count: number
  5. }
  6. export  const key: InjectionKey<Store<State>> = Symbol()
  7. export  const store = createStore<State>({
  8.   state() {
  9.      return {
  10.       count:  0
  11.     }
  12.   },
  13.   mutations: {
  14.     increment(state) {
  15.       state.count++
  16.     }
  17.   }
  18. })

main.ts 修改


   
  1. import { createApp } from  'vue'
  2. import { store, key } from  './store'
  3. import App from  './App'
  4. import  './index.css'
  5. const app = createApp(App)
  6. app.use(store, key)
  7. app.mount( '#app')

components/HelloWord.vue 修改


   
  1. <template>
  2.   <h1>{{ msg }}</h1>
  3.   <button @click= "inCrement"> count is: </button>
  4.   <p>{{ count }}</p>
  5. </template>
  6. <script>
  7.    import { defineComponent, computed } from  'vue'
  8.    import { useStore } from  'vuex'
  9.    import { key } from  '../store'
  10.   export  default defineComponent({
  11.     name:  'HelloWorld',
  12.     props: {
  13.       msg: {
  14.          type: String,
  15.          default''
  16.       }
  17.     },
  18.     setup() {
  19.        const store = useStore(key)
  20.        const count = computed(() => store.state.count)
  21.        return {
  22.         count,
  23.         inCrement: () => store.commit( 'increment')
  24.       }
  25.     }
  26.   })
  27. </script>

4.2 vue-router

在 src 目录下建立 router/index.ts,内容如下:


   
  1. import { createRouter, createWebHistory, RouteRecordRaw } from  "vue-router";
  2. import HelloWorld from  "../components/HelloWorld.vue";
  3. const routes: Array<RouteRecordRaw> = [
  4.     {
  5.         path:  "/",
  6.         name:  "HelloWorld",
  7.         component: HelloWorld,
  8.     },
  9.     {
  10.         path:  "/about",
  11.         name:  "About",
  12.          // route level code-splitting
  13.          // this generates a separate chunk (about.[hash].js) for this route
  14.          // which is lazy-loaded when the route is visited.
  15.         component: () =>
  16.              import( /* webpackChunkName: "About" */  "../components/About.vue")
  17.     }
  18. ];
  19. const router = createRouter({
  20.     history: createWebHistory(process.env.BASE_URL),
  21.     routes,
  22. });
  23. export  default router;

再新建一个 components/About.vue 文件,内容如下:


   
  1. <template>
  2.   <img
  3.     alt= "Vue logo"
  4.     src= "../assets/logo.png"
  5.   />
  6.   <h1>{{ msg }}</h1>
  7. </template>
  8. <script lang= "ts">
  9. import { defineComponent } from  'vue'
  10. export  default defineComponent({
  11.   name:  'About',
  12.   data() {
  13.      return {
  14.       msg:  'Hello Vue 3.0 + Vite!'
  15.     }
  16.   },
  17.   setup() {}
  18. })
  19. </script>

再修改 main.ts


   
  1. import { createApp } from  'vue'
  2. import { store, key } from  './store'
  3. import router from  "./router";
  4. import App from  './App'
  5. import  './index.css'
  6. const app = createApp(App)
  7. app.use(store, key)
  8. app.use(router)
  9. app.mount( '#app')

再访问 http://localhost:3000/

和 http://localhost:3000/about 即可

5. 加入 Element Plus

5.1 安装 element-plus

全局安装

npm install element-plus --save

5.2 引入 Element Plus

你可以引入整个 Element Plus,或是根据需要仅引入部分组件。我们先介绍如何引入完整的 Element。

完整引入

在 main.js 中写入以下内容:


   
  1. import { createApp } from  'vue'
  2. import ElementPlus from  'element-plus';
  3. import router from  "./router";
  4. import  'element-plus/lib/theme-chalk/index.css';
  5. import App from  './App.vue';
  6. import  './index.css'
  7. const app = createApp(App)
  8. app.use(ElementPlus)
  9. app.use(router)
  10. app.mount( '#app')

以上代码便完成了 Element Plus 的引入。需要注意的是,样式文件需要单独引入。


按需引入

借助 babel-plugin-component,我们可以只引入需要的组件,以达到减小项目体积的目的。

首先,安装 babel-plugin-component:

npm install babel-plugin-component -D

然后,将 .babelrc 修改为:


   
  1. {
  2.    "plugins": [
  3.     [
  4.        "component",
  5.       {
  6.          "libraryName""element-plus",
  7.          "styleLibraryName""theme-chalk"
  8.       }
  9.     ]
  10.   ]
  11. }

接下来,如果你只希望引入部分组件,比如 Button 和 Select,那么需要在 main.js 中写入以下内容:


   
  1. import { createApp } from  'vue'
  2. import { store, key } from  './store';
  3. import router from  "./router";
  4. import { ElButton, ElSelect } from  'element-plus';
  5. import App from  './App.vue';
  6. import  './index.css'
  7. const app = createApp(App)
  8. app.component(ElButton.name, ElButton);
  9. app.component(ElSelect.name, ElSelect);
  10. /* or
  11.  * app.use(ElButton)
  12.  * app.use(ElSelect)
  13.  */
  14. app.use(store, key)
  15. app.use(router)
  16. app.mount( '#app')
  17. app.mount( '#app')

更详细的安装方法请看 快速上手。

5.3 全局配置

在引入 Element Plus 时,可以传入一个全局配置对象。

该对象目前支持 size 与 zIndex 字段。size 用于改变组件的默认尺寸,zIndex 设置弹框的初始 z-index(默认值:2000)。按照引入 Element Plus 的方式,具体操作如下:

完整引入 Element:


   
  1. import { createApp } from  'vue'
  2. import ElementPlus from  'element-plus';
  3. import App from  './App.vue';
  4. const app = createApp(App)
  5. app.use(ElementPlus, { size:  'small', zIndex:  3000 });

按需引入 Element:


   
  1. import { createApp } from  'vue'
  2. import { ElButton } from  'element-plus';
  3. import App from  './App.vue';
  4. const app = createApp(App)
  5. app.config.globalProperties.$ELEMENT = option
  6. app.use(ElButton);

按照以上设置,项目中所有拥有 size 属性的组件的默认尺寸均为 'small',弹框的初始 z-index 为 3000。

最后

至此,一个基于 Vue3 全家桶 + Vite + TypeScript + Eslint + Element Plus 的开发环境已经搭建完毕,现在就可以编写代码了。

各个组件的使用方法请参阅它们各自的文档。

不得不说 Vue3 + Element Plus + Vite + TypeScript 是真的香!

推荐一个 Vue3 相关的资料汇总:Vue3 的学习教程汇总、源码解释项目、支持的 UI 组件库、优质实战项目,相信你会挖到矿哦!

Vue3 中文文档,国内 CDN 加速版:

https://vue3js.cn/docs/zh/

Element Plus 官网:

https://element-plus.org/#/zh-CN


作为 2021 第 2 篇原创技术文章,质量应该还可以吧,1 月的 KPI 完成,哈哈哈 ????

猫哥的年终总结在这里:前端工程师的 2020 年终总结 - 乾坤未定,你我皆黑马,希望能带给你一点启发,也看看猫哥的脸都被打歪的 ????

参考文章:vue3 + vite + typescript + eslint + jest 项目配置实践

推荐阅读


转载:https://blog.csdn.net/ch834301/article/details/113578048
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场