zoukankan      html  css  js  c++  java
  • vite-v3-ts-0到0.8

    从0到0.8

    1. vite 创建项目
    2. eslint
    3. prettier
    4. EditorConfig
    5. 提交代码检测:husky && lint-staged
    6. proxy
    7. env-development
    8. 引入vuex@next
    9. 引入vue-router@next
    10. 引入axios
    11. 按需引入element-plus
    12. 引入scss及初始化样式


    vite 创建项目

    • npm init @vitejs/app demo-name


    eslint

    1. 安装 eslint: npm install eslint --save-dev
    2. 初始化 eslint 文件:npx eslint --init自动生成.eslintrc.js 文件
    3. 配置 rules、settings,.eslintrc.js 文件:
    // .eslintrc.js
    module.exports = {
      env: {
        browser: true,
        es2021: true,
      },
      extends: [
        'plugin:vue/essential',
        'airbnb-base',
      ],
      parserOptions: {
        ecmaVersion: 12,
        parser: '@typescript-eslint/parser',
        sourceType: 'module',
      },
      plugins: [
        'vue',
        '@typescript-eslint',
      ],
      rules: {
        'import/no-unresolved': 'off',
        'import/extensions': 'off',
        'import/no-extraneous-dependencies': 'off',
      },
      settings: {
        'import/resolver': {
          alias: {
            map: [
              ['@', './src'],
            ],
          },
        },
      },
    };
    
    
    1. vite.config.ts 配置了别名之后,tsconfig 也需要配置 paths/baseUrl
    // vite.config.ts
    {
      "compilerOptions": {
        "target": "esnext",
        "module": "esnext",
        "moduleResolution": "node",
        "strict": true,
        "jsx": "preserve",
        "sourceMap": true,
        "resolveJsonModule": true,
        "esModuleInterop": true,
        "lib": ["esnext", "dom"],
        "baseUrl": "./",
        "paths": {
          "@/*": ["./src/*"],
        }
      },
      "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
    }
    
    
    1. 可建.eslintignore 忽略不需要 eslint 检测的文件
    /node_modules/
    
    


    prettier

    1. 安装npm install --save-dev eslint-plugin-prettier npm install --save-dev --save-exact prettier npm install --save-dev eslint-config-prettier
    2. plugin:prettier/recommended 的配置需要注意的是,一定要放在最后。因为 extends 中后引入的规则会覆盖前面的规则。
    3. eslint 的插件 eslint-config-prettier,这个插件的作用是禁用所有与格式相关的 eslint 规则,也就是说把所有格式相关的校验都交给 prettier 处理。
    4. 修改.eslintrc.js:
    // .eslintrc.js
    extends: [
      "plugin:vue/vue3-recommended",
      "airbnb-base",
      "plugin:prettier/recommended",
    ],
    rules: {
      "prettier/prettier": "off",
    },
    
    
    1. 新建.prettierrc.js 自定义 prettier 规则:
    // .prettierrc.js
    module.exports = {
      useTabs: false,
      tabWidth: 2,
      printWidth: 100,
      singleQuote: true,
      trailingComma: 'es5',
      bracketSpacing: true,
      semi: true,
    };
    
    
    • ps: 项目中的 prettier 配置生效前提是有动作促使它执行,如 vscode 的 settings.json 中"editor.formatOnSave": true,保存格式化会执行项目中的 prettier 文件,项目中没有该文件会执行编辑器自带的 prettier。


    EditorConfig

    1. vscode 安装 EditorConfig for VS Code 插件
    2. 根目录下新建.editorconfig 文件:
    // .editorconfig
    # Editor configuration, see http://editorconfig.org
    
    # 表示是最顶层的 EditorConfig 配置文件
    root = true
    
    [*] # 表示所有文件适用
    charset = utf-8 # 设置文件字符集为 utf-8
    indent_style = space # 缩进风格(tab | space)
    indent_size = 2 # 缩进大小
    end_of_line = lf # 控制换行类型(lf | cr | crlf)
    trim_trailing_whitespace = true # 去除行尾的任意空白字符
    insert_final_newline = true # 始终在文件末尾插入一个新行
    curly_bracket_next_line = true # 大括号不另起一行
    spaces_around_operators = true # 运算符两遍都有空格
    
    [*.md] # 表示仅 md 文件适用以下规则
    max_line_length = off
    trim_trailing_whitespace = false
    
    


    提交代码检测:husky && lint-staged

    1. husky,主要用于关联 git 的钩子函数,在执行相关 git hooks 时候进行自定义操作,如提交前进行 eslint 校验,提交时检验 commit message 等;, npx husky-init && npm install,
    2. v7 版本执行命令后会生成.husky 文件夹,pre-commit 文件便是在 git 提交前会执行的操作,想要在提交前执行 eslint 校验代码,因此修改 husky 的 pre-commit 文件即可:
    #!/bin/sh
    . "$(dirname "$0")/_/husky.sh"
    # npm test
    eslint . --ext .js, .ts, .vue --fix # 校验所有的js-ts-vue文件并修复可自动修复的问题
    git add . # 用于将自动修复后盖板的文件添加到暂存区
    exit 1 # 终止命令,用来测试钩子
    
    1. lint-staged:只对暂存区的文件执行 lint,可以实现每次提交时只校验自己修改的文件,npm install lint-staged --save-dev
    2. 修改 package.json 文件
     "scripts": {
        "dev": "vite",
        "build": "vue-tsc --noEmit && vite build",
        "serve": "vite preview",
        "prepare": "husky install",
        "lint-staged": "lint-staged"
      },
      "lint-staged": {
        "*.{ts,js,vue}": [
          "eslint --fix",
          "git add ."
        ]
      },
    
    1. 修改 husky:添加 lint-staged 配置后,husky 就不在需要直接调用 eslint 了,修改.husky/pre-commit 文件:
    #!/bin/sh
    . "$(dirname "$0")/_/husky.sh"
    # npm test
    # eslint . --ext .js, .ts, .vue --fix # 校验所有的js-ts-vue文件并修复可自动修复的问题
    # git add . # 用于将自动修复后盖板的文件添加到暂存区
    # exit 1 # 终止命令,用来测试钩子
    
    npm run lint-staged
    
    


    proxy && port && alias

    1. 新建 compile/proxy.ts 文件
    module.exports = {
      '/api': {
        target: 'https://*.**.com/',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^/api/, ''),
      },
    };
    
    
    1. 修改 vite.config.ts 文件
    import { defineConfig } from 'vite';
    import vue from '@vitejs/plugin-vue';
    const proxy = require('./compile/proxy');
    export default defineConfig({
      plugins: [
        vue(),
      ],
      server: {
        port: 6688,
        open: true,
        cors: true,
        // 为开发服务器配置自定义代理规则
        proxy,
      },
      // 别名
      resolve: {
        alias: {
          '@': path.resolve(__dirname, 'src'),
        },
      },
    });
    
    1. 修改 eslintrc.js 文件:
      settings: {
        'import/resolver': {
          alias: {
            map: [['@', './src']],
          },
        },
      },
    
    1. 修改 tsconfig.json 文件:
    {
      "compilerOptions": {
        "paths": {
          "@/*": ["./src/*"],
        }
      }
    }
    


    env-development 环境变量

    1. src/.env.development 文件: VITE_BASE_URL = /api
    2. 对应类型声明文件 src/.env.d.ts:
    // 建议类型声明文件,方便.提醒,.出存在字段
    // 环境变量提醒
    // eslint-disable-next-line no-unused-vars
    interface ImportMetaEnv {
      VITE_BASE_URL: string;
    }
    
    • ps:这里定义的 VITE_BASE_URL 可用于封装 axios 时的 baseURL 取值;


    引入 vuex@next

    • npm i vuex@next -S
    • 引入四步骤
      1. 创建 store 文件夹,并创建 index.ts 文件
      2. 在根目录下创建 vuex 的类型声明文件 vuex.d.ts
      3. 模块化,store/modules/user.ts
      4. main.ts 中引入 Store
      5. 组件中使用 state
    • useStore()类型化:setup 中使用 useStore 时要类型化,三步骤
      1. 定义InjectionKey store/index.ts 中
      2. app 安装时提供InjectionKey main.ts
      3. 传递InjectionKeyuseStore 组件中使用如 CompVuex.vue
    // store/index.ts
    import { InjectionKey } from 'vue';
    import { createStore, Store } from 'vuex';
    import users, { UserState} from './modules/todolist';
    
    export type State = {
      ac: number;
      users?: UserState;
    };
    
    // 泛型 核心目的 约束State
    // 1. 创建一个injectionKey
    export const key: InjectionKey<Store<State>> = Symbol('description');
    
    export default createStore({
      state: {
        ac: 0,
      },
      mutations: {
        add(state) {
          Object.assign(state, {
            ac: state.ac + 1,
          });
        },
      },
      // 声明子模块
      modules: {
        users,
      },
    });
    
    

    // modules/list.ts
    import { Module } from 'vuex';
    import { State } from '../index';
    import { Item} from '../../types';
    import http from '../../api/request';
    
    const initialState = {
      list: [] as Item[],
    };
    
    // 从已有值中推断出类型
    export type UserState= typeof initialState;
    
    // Module<S, R>泛型约束 S 子模块的类型 R根模块的类型
    export default {
      namespaced: true,
      // 子模块state
      state: initialState,
      mutations: {
        initItem(state, payload: Item[]) {
          // eslint-disable-next-line no-param-reassign
          state.list = payload;
        },
        addItem(state, payload: Item) {
          state.list.push(payload);
        },
      },
      actions: {
        getList() {
          http.get('/*').then((res) => {
            console.log('res: ', res);
          });
        },
        init({ commit }) {
          // 使用相对路径,从而可以被我们的代理所接管,在vite.config.ts中配置代理
          // <Item>请求返回的类型
          http.get<Item>('/*').then((resp) => {
            commit('add', resp.data);
          });
        },
        add({commit, state }, payload: string) {
          commit('add', {
            id: state.list.length + 1,
            title: payload,
            completed: false,
          } as Item);
        },
      },
    } as Module<UserState, State>;
    
    

    // main.ts
    import store, { key } from './store/index';
    // 2. App注入key
    createApp(App)use(store, key).mount('#app');
    

    // 组件中使用
    <script lang="ts" setup>
    import { computed, defineProps, PropType } from 'vue';
    import { useStore } from 'vuex';
    import { key } from '../store';
    import { TitleInfo } from '../types';
    // 有了useStore之后所有的值都被认为计算属性处理
    
    // 3.传递`InjectionKey`给`useStore` 方便于属性提醒
    const store = useStore(key);
    // 全局state
    const cc = computed(() => store.state.c);
    // 子模块state
    console.log(computed(() => store.state.users?.list));
    // users初始化 类似于请求接口 store/index.ts加了命名空间,请求接口时候需要带上
    store.dispatch('users/init', 'kk');
    // 定义属性
    defineProps({
      titleInfo: {
        type: Object as PropType<TitleInfo>,
        required: true,
      },
    });
    </script>
    

    // 根目录types.d.ts
    export type TitleInfo = {
      value: string;
      color: string;
    };
    
    
    export type Item= {
      id: number;
      title: string;
      completed: boolean;
    };
    
    


    引入 vue-router@next

    • 安装npm i vue-router@next -S
    • 引入 src/router/index.ts 创建实例
    • App.vue 中设置路由出口,可能还有路由导航
    • main.ts 中 use 路由
    // router/index.ts
    // 路由实例,ts默认支持路由,则不需要额外添加类型声明文件
    import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
    
    // 对路由定义对象进行扩展,如增加新的字段hidden
    export type AppRouteRecordRaw = RouteRecordRaw & {
      hidden?: boolean;
    };
    
    const router = createRouter({
      history: createWebHashHistory(),
      // 路由 类型断言
      routes: [
        {
          path: '/',
          component: () => import('../pages/Home.vue'),
          meta: {
            title: 'kkk',
            icon: 'el-icon-edit',
          },
        },
        {
          path: '/add',
          hidden: true,
          component: () => import('../pages/About.vue'),
        },
      ] as AppRouteRecordRaw[],
    });
    
    // 路由守卫
    router.beforeEach((to, from, next) => {
      console.log('to, from, next: ', to, from, next);
      return next();
    });
    export default router;
    
    

    // App.vue
     <!--路由出口-->
     <router-link to="/">todo</router-link>
     <router-link to="/add">add</router-link>
     <router-view></router-view>
    

    // main.ts
    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router';
    
    // 2. app安装时提供`InjectionKey`
    createApp(App).use(router).mount('#app')
    
    


    axios

    • 安装npm i axios -S
    • 新建 src/api/request.ts
    • 创建 axios 实例,统一处理、统一配置


    按需引入 element-plus

    1. 安装npm install element-plus --save
    2. main.ts 中完整引入
    import ElementPlus from 'element-plus';
    import 'element-plus/lib/theme-chalk/index.css';
    createApp(App).use(ElementPlus)
    
    1. vite.config.ts 配置按需引入
    import styleImport from 'vite-plugin-style-import';
    export default defineConfig({
      plugins: [
        vue(),
        styleImport({
          libs: [
            {
              libraryName: 'element-plus',
              esModule: true,
              ensureStyleFile: true,
              resolveStyle: (name) => {
                const nameTemp = name.slice(3);
                return `element-plus/packages/theme-chalk/src/${nameTemp}.scss`;
              },
              resolveComponent: (name) => `element-plus/lib/${name}`,
            },
          ],
        }),
      ],
    });
    
    1. 组件页面中使用 ElementPlus
     <el-button type="primary">主要按钮</el-button>
    


    引入 scss 及初始化样式

    1. npm install sass -D npm i normalize.css -S
    2. 新建variables.scss,element-theme.scss,helpers.scss,reset.scss






    参考 && 感谢 各路大神:

    editorconfig
    Vue3+Vite+TS+Eslint-搭建项目,配置 ESLint
    Vue3+Vite+TS+Eslint-配置 husky 和 lint-staged
    Vue3+Vite+TS+Eslint-引入 Element-plus,解决字体文件 404 问题
    Vue3+Vite+TS+Eslint-引入 vuex、vuex 源码类型声明推导
    体验 vite + vue3 + ts 搭建项目的全过程
    ElementPlus
    杨村长-Vue3+Typescript 从整合到项目实战
    宝剑锋从磨砺出,梅花香自苦寒来。
  • 相关阅读:
    新组件或功能怎么依附到已有的架构上
    高内聚、低耦合
    软件质量的定义
    软件架构与组件
    架构设计之拥抱着变化而设计(部分讲义分享)
    组件设计原则之概念篇(四)
    抽象类(接口类)的作用
    类,抽象基类,接口类三者间的区别与联系(C++)
    软件的可变性
    软件设计的复杂度
  • 原文地址:https://www.cnblogs.com/haimengqingyuan/p/15130718.html
Copyright © 2011-2022 走看看