超详细保姆级vue3和代码规范项目搭建

vue3-admin项目搭建

项目初始化

创建 git 仓库

npm 管理工具

pnpm 安装

pnpm create vite zf-v3-admin –template vue-ts

pnpm init 初始化package.json

创建pnpm-workspace.yaml 定义工作区

pnpm-lock.yaml 和 package-lock.json 都是项目中的锁定文件,它们的作用是锁定项目所依赖的包的版本。

pnpm-lock.yaml 是由 pnpm(一个 JavaScript 包管理工具)生成的锁定文件,它记录了所有项目依赖的包的版本。

package-lock.json 是 NPM(Node Package Manager,一个 JavaScript 包管理工具)生成的锁定文件,它也记录了所有项目依赖的包的版本。

代码风格统一

vue3+ts+vite项目中使用eslint+prettier+stylelint+husky指南 - 掘金

配置ESLint + Prettier

安装对应包

pnpm add eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-plugin-prettier eslint-config-prettier prettier eslint-plugin-vue @vue/eslint-config-prettier @vue/eslint-config-typescript -Dw

根目录创建以下配置文件以及内容如下

  • .esintrc.js:基础eslint配置,支持ts,结合prettier

    module.exports = {
      root: true,
      env: {
        browser: true,
        node: true,
        es6: true,
      },
      extends: [
        "plugin:vue/vue3-essential",
        "eslint:recommended",
        "@vue/typescript/recommended",
        "@vue/prettier",
        "@vue/eslint-config-typescript",
      ],
      parser: "vue-eslint-parser",
      parserOptions: {
        parser: "@typescript-eslint/parser",
        ecmaVersion: 2020,
        sourceType: "module",
        jsxPragma: "React",
        ecmaFeatures: {
          jsx: true,
          tsx: true,
        },
      },
      rules: {
        // TS
        "@typescript-eslint/no-explicit-any": "off",
        "no-debugger": "off",
        "@typescript-eslint/explicit-module-boundary-types": "off",
        "@typescript-eslint/ban-types": "off",
        "@typescript-eslint/ban-ts-comment": "off",
        "@typescript-eslint/no-empty-function": "off",
        "@typescript-eslint/no-non-null-assertion": "off",
        "@typescript-eslint/no-unused-vars": [
          "error",
          {
            argsIgnorePattern: "^_",
            varsIgnorePattern: "^_",
          },
        ],
        "no-unused-vars": [
          "error",
          {
            argsIgnorePattern: "^_",
            varsIgnorePattern: "^_",
          },
        ],
        // Vue
        "vue/no-v-html": "off",
        "vue/require-default-prop": "off",
        "vue/require-explicit-emits": "off",
        "vue/multi-word-component-names": "off",
        "vue/html-self-closing": [
          "error",
          {
            html: {
              void: "always",
              normal: "always",
              component: "always",
            },
            svg: "always",
            math: "always",
          },
        ],
        // Prettier
        "prettier/prettier": [
          "error",
          {
            endOfLine: "auto",
          },
        ],
      },
    };
    
  • eslintrc.vue3.js:vue3项目的eslint配置,工作区内的vue3项目可都引用此配置

    /* eslint-env node */
      require('@rushstack/eslint-patch/modern-module-resolution')
    
      module.exports = {
        root: true,
        extends: [
          './.eslintrc.js',
          'plugin:vue/vue3-recommended',
          '@vue/eslint-config-typescript',
          // 如需跳过prettier改成'@vue/eslint-config-prettier/skip-formatting',
          '@vue/eslint-config-prettier',
        ],
        plugins: [
          // eslint-plugin-vue 缩写
          // plugin:vue/vue3-recommended->basse内部plugins配置了vue插件,
          // 同样这里不配置vue也行
          'vue'
        ],
      }
    
  • .prettier.config.js

    /** 配置项文档:https://prettier.io/docs/en/configuration.html */
    module.exports = {
      /** 每一行的宽度 */
      printWidth: 120,
      /** Tab 键的空格数 */
      tabWidth: 2,
      /** 在对象中的括号之间是否用空格来间隔 */
      bracketSpacing: true,
      /** 箭头函数的参数无论有几个,都要括号包裹 */
      arrowParens: "always",
      /** 换行符的使用 */
      endOfLine: "auto",
      /** 是否采用单引号 */
      singleQuote: false,
      /** 对象或者数组的最后一个元素后面不要加逗号 */
      trailingComma: "none",
      /** 是否加分号 */
      semi: false,
      /** 是否使用 Tab 格式化 */
      useTabs: false,
    };
    
  • .eslintignore .prettierignore

    node_modules/*
    dist/*
    asset/*
    *.d.ts
    
  • package.json添加执行脚本

    
    "lint:eslint": "eslint --cache --max-warnings 0 \"{src,tests,types}/**/*.{vue,js,jsx,ts,tsx}\" --fix",
    "lint:prettier": "prettier --write \"{src,tests,types}/**/*.{vue,js,jsx,ts,tsx,json,css,less,scss,html,md}\"",
    "lint": "pnpm lint:eslint && pnpm lint:prettier",
    

Ps:配置好后会报错 Prettier 3.0.0 TypeError: prettier.resolveConfig.sync is not a function

原因是:prettier 和eslint两个包的冲突

配置Stylelint + Prettier

Stylelint 和 ESLint的配置是极为相似的

  1. 安装

    pnpm add stylelint stylelint-config-standard stylelint-config-standard-scss stylelint-config-standard-vue stylelint-config-prettier stylelint-order stylelint-prettier -Dw
    
    
  2. 根目录创建配置文件

    • stylelint.config.js

      module.exports = {
        extends: [
          "stylelint-config-standard-scss",
          "stylelint-config-standard-vue/scss",
          "stylelint-prettier/recommended",
          "stylelint-config-prettier",
        ],
        plugins: ["stylelint-order", "stylelint-prettier"],
        rules: {
          "order/properties-order": [
            "display",
            "position",
            "float",
            "top",
            "right",
            "bottom",
            "left",
            "z-index",
            "width",
            "height",
            "max-width",
            "max-height",
            "min-width",
            "min-height",
            "padding",
            "padding-top",
            "padding-right",
            "padding-bottom",
            "padding-left",
            "margin",
            "margin-top",
            "margin-right",
            "margin-bottom",
            "margin-left",
            "margin-collapse",
            "margin-top-collapse",
            "margin-right-collapse",
            "margin-bottom-collapse",
            "margin-left-collapse",
            "overflow",
            "overflow-x",
            "overflow-y",
            "clip",
            "clear",
            "font",
            "font-family",
            "font-size",
            "font-smoothing",
            "osx-font-smoothing",
            "font-style",
            "font-weight",
            "line-height",
            "letter-spacing",
            "word-spacing",
            "color",
            "text-align",
            "text-decoration",
            "text-indent",
            "text-overflow",
            "text-rendering",
            "text-size-adjust",
            "text-shadow",
            "text-transform",
            "word-break",
            "word-wrap",
            "white-space",
            "vertical-align",
            "list-style",
            "list-style-type",
            "list-style-position",
            "list-style-image",
            "pointer-events",
            "cursor",
            "background",
            "background-color",
            "border",
            "border-radius",
            "content",
            "outline",
            "outline-offset",
            "opacity",
            "filter",
            "visibility",
            "size",
            "transform",
          ],
        },
      };
      
    • .stylelintignore

      node_modules/*
      dist/*
      public/*
      
    • package.json添加执行脚本

      {
         "scripts":{
             // ...
             "lint:css": "stylelint **/*.{vue,css,sass,scss} --fix",
         }
      }
      

husky + lint-staged 规范提交信息,执行格式校验

  1. git 仓库

  2. 安装

    pnpm add husky lint-staged @commitlint/config-conventional @commitlint/cli -Dw
    
  3. 创建.husky文件夹(执行husky安装命令)

    pnpx husky install
    
  4. 添加钩子

    1. pre-commit:

      pnpx husky add .husky/pre-commit "npx lint-staged"
      
    2. commit-msg:

      pnpx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"
      
  5. 修改packages.json,配置提交前需要执行的脚本。

    {
       "scripts": {
        "dev": "vite",
        "build:stage": "vue-tsc --noEmit && vite build --mode staging",
        "build:prod": "vue-tsc --noEmit && vite build",
        "preview:stage": "pnpm build:stage && vite preview",
        "preview:prod": "pnpm build:prod && vite preview",
        "lint:eslint": "eslint --cache --max-warnings 0 \"{src,tests,types}/**/*.{vue,js,jsx,ts,tsx}\" --fix",
        "lint:prettier": "prettier --write \"{src,tests,types}/**/*.{vue,js,jsx,ts,tsx,json,css,less,scss,html,md}\"",
        "lint": "pnpm lint:eslint && pnpm lint:prettier",
        "prepare": "husky install",
        "test": "vitest"
       },
       "lint-staged": {
        "*.{vue,js,jsx,ts,tsx}": [
          "eslint --fix",
          "prettier --write"
        ],
        "*.{css,less,scss,html,md}": [
          "prettier --write"
        ],
        "package.json": [
          "prettier --write"
        ]
      },
    }
    
  6. 项目根目录新建commitlint.config.js配置文件,规范提交信息。参考配置如下

    // commitlint.config.js
    module.exports = {
      extends: ['@commitlint/config-conventional'],
      rules: {
        /**
         配置含义
          name: [ 
            等级( 0: disable,1: warning, 2: error ), 
            生效与否( always, never ),
            值
          ]
         */
        'type-enum': [
          2,
          'always',
          [
            'upd', // 更新某功能
            'feat', // 新增功能(feature)
            'fix', // 修复补丁(bug)
            'refactor', // 代码重构,未新增任何功能和修复任何 bug
            'docs', // 修订文档
            'style', // 仅调整空格、格式缩进等(不改变代码逻辑的变动)
            'test', // 测试用例的增加/修改
            'perf', // 优化相关,改善性能和体验的修改
            'chore', // 构建过程和辅助工具的变动
            'merge', // 合并分支或冲突等
            'revert', // 回滚到上一个版本
            'build',  //改变构建流程,新增依赖库、工具等(例如 webpack、maven 修改)
            'ci' //自动化流程配置修改
          ],
        ],
        'type-case': [0],
        'type-empty': [0],
        'scope-empty': [0],
        'scope-case': [0],
        'subject-full-stop': [0, 'never'],
        'subject-case': [0, 'never'],
        'header-max-length': [0, 'always', 72],
      },
    }
    

自动生成changelog及项目版本管理

  1. 版本管理

    1. version类别介绍

      每个npm包中都有一个package.json文件,如果要发包的话,package.json中的version就是版本号了。

      version字段结构为:'0.0.0-0’

      分别代表:大号.中号.小号-预发布号,对应majon.minor.patch-prerelease

      npm中version的类别及描述:

      • major

        • 如果没有预发布号,则直接升级一位大号,其他位都置为0
        • 如果有预发布号
            1. 中号和小号都为0,则不升级大号,而将预发布号删掉。即2.0.0-1变成2.0.0,这就是预发布的作用
            1. 如果中号和小号有任意一个不是0,那边会升级一位大号,其他位都置为0,清空预发布号。即 2.0.1-0变成3.0.0
      • minor

        • 如果没有预发布号,则升级一位中号,大号不动,小号置为空(2.0.1⇒ 2.1.0)
        • 如果有预发布号:
          • 如果小号为0,则不升级中号,将预发布号去掉
          • 如果小号不为0,同理没有预发布号
      • patch

        • 如果没有预发布号:直接升级小号,去掉预发布号
        • 如果有预发布号:去掉预发布号,其他不动
      • premajor

        • 直接升级大号,中号和小号置为0,增加预发布号为0
      • preminor

        • 直接升级中号,小号置为0,增加预发布号为0
      • prepatch

        • 直接升级小号,增加预发布号为0
      • prerelease

        • 如果没有预发布号:增加小号,增加预发布号为0
        • 如果有预发布号,则升级预发布号
  2. 生成 Change log

    pnpm add  conventional-changelog-cli  -w
    

    package.json

    {
      "scripts": {
       "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
      } 
    }
    

项目基础基本设置

  1. TS 配置修改

    1. 创建完成后tsconfig.json中有几处配置会爆红,需要修改配置
    {
      "compilerOptions": {
        "target": "esnext",
        /** https://cn.vitejs.dev/guide/features.html#typescript-compiler-options */
        "useDefineForClassFields": true,
        "module": "esnext",
        "moduleResolution": "node",
        /** TS 严格模式 */
        "strict": true,
        "jsx": "preserve",
        "importHelpers": true,
        "experimentalDecorators": true,
        "allowSyntheticDefaultImports": true,
        "sourceMap": true,
        "resolveJsonModule": true,
        /** https://cn.vitejs.dev/guide/features.html#typescript-compiler-options */
        "isolatedModules": true,
        "esModuleInterop": true,
        "lib": ["esnext", "dom"],
        "skipLibCheck": true,
        "types": [
          "node",
          "vite/client",
          /** Element Plus 的 Volar 插件支持 */
          "element-plus/global",
          "vitest"
        ],
        /** baseUrl 用来告诉编译器到哪里去查找模块,使用非相对模块时必须配置此项 */
        "baseUrl": ".",
        /** 非相对模块导入的路径映射配置,根据 baseUrl 配置进行路径计算 */
        "paths": {
          "@/*": ["src/*"]
        }
      },
      "include": [
        "src/**/*.ts",
        "src/**/*.d.ts",
        "src/**/*.tsx",
        "src/**/*.vue",
        "tests/**/*.ts",
        "types/**/*.d.ts",
        "vite.config.ts",
        "vitest.config.ts"
      ],
      /** 编译器默认排除的编译文件 */
      "exclude": ["node_modules", "dist"]
    }
    
  2. 配置路径别名@

    1. 安装@types/node

      pnpm add -D @types/node -w
      
    2. 修改vite.config.ts配置路径别名@

      import { defineConfig } from "vite";
      import vue from "@vitejs/plugin-vue";
      import path from "path"; //这个path用到了上面安装的@types/node
      
      // https://vitejs.dev/config/
      export default defineConfig({
        plugins: [vue()],
        //这里进行配置别名
        resolve: {
          alias: {
            "@": path.resolve("./src"), // @代替src
          },
        },
      });
      
    3. 修改tsconfig.json 中的信息

      "compilerOptions": {
      	
      	//添加如下信息
          "baseUrl": "./",	// 解析非相对模块的基地址,默认是当前目录
          "paths": {"@/*": ["src/*"]}	// 路径映射,相对于baseUrl
        },
      
  3. 端口代理配置

    vite.config.ts 文件

    export default defineConfig({
      server: {
        /** 是否开启 HTTPS */
        https: false,
        /** 设置 host: true 才可以使用 Network 的形式,以 IP 访问项目 */
        host: true, // host: "0.0.0.0"
        /** 端口号 */
        port: 3333,
        /** 是否自动打开浏览器 */
        open: false,
        /** 跨域设置允许 */
        cors: true,
        /** 端口被占用时,是否直接退出 */
        strictPort: false,
        /** 接口代理 */
        proxy: {
          "/api/v1": {
            target:
              "https://mock.mengxuegu.com/mock/63218b5fb4c53348ed2bc212/api/v1",
            ws: true,
            /** 是否允许跨域 */
            changeOrigin: true,
            rewrite: (path) => path.replace("/api/v1", ""),
          },
        },
      },
    })
    
  4. bulid 配置

    vite.config.ts 文件

    export default defineConfig({
     build: {
        /** 消除打包大小超过 500kb 警告 */
        chunkSizeWarningLimit: 2000,
        /** Vite 2.6.x 以上需要配置 minify: "terser", terserOptions 才能生效 */
        minify: "terser",
        /** 在打包代码时移除 console.log、debugger 和 注释 */
        terserOptions: {
          compress: {
            drop_console: false,
            drop_debugger: true,
            pure_funcs: ["console.log"],
          },
          format: {
            /** 删除注释 */
            comments: false,
          },
        },
        /** 打包后静态资源目录 */
        assetsDir: "static",
      },
    })
    

安装element-plus(ui组件库 Ant Design Vue同理)

PS: 因为Ant Design Vue table ,定义好 columns 有几列后,用 template 写法就无法用 v-if 去隐藏某一列()

Element Plus 和 Ant Design Vue 的分析对比 - 掘金

  1. 安装less/scss

    1. 安装less

      pnpm add -D less less-loader -w
      
    2. 安装scss

      pnpm add -D less sass node-sass -w
      

      ps: 留个小坑下面是解决方案

      Human verification

  2. 安装element-plus(推荐按需导入和手动导入)

    安装 | Element Plus

    1. 导入element 的图标集合

      pnpm install @element-plus/icons-vue -w
      

      全局注册: 创建plugin然后创建element-plus-icon目录增加index.ts

      import { type App } from "vue"
      import * as ElementPlusIconsVue from "@element-plus/icons-vue"
      
      export function loadElementPlusIcon(app: App) {
        /** 注册所有 Element Plus Icon */
        for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
          app.component(key, component)
        }
      }
      

      使用:

      <script setup lang="ts">
      import { Setting } from "@element-plus/icons-vue";
      
      </script>
      
      <template>
        <Setting />
      </template>
      
      <style scoped>
      
      </style>
      

安装pinia

Pinia 🍍

  1. 导包

    pnpm install -D  pinia  -w
    
  2. 创建pinia,在src/stroes目录下创建index.ts文件,添加下面的内容:

    import { createPinia } from "pinia"
    
    const store = createPinia()
    
    export default store
    
  3. main.ts中注册pinia

    import { createApp } from "vue";
    import "./style.css";
    import App from "@/App.vue";
    import store from "@/store";
    const app = createApp(App);
    app.use(store).mount("#app");
    
  4. 在src下创建一个 store/user.ts 文件

    什么名字可以,因为pinia它有一个根文件,会把 defineStore 第一个参数当id值,相当于vuex中的 module 自动引入,也会在Vue.js devtools 插件中以第一个参数名展示(下面展示)

    注意:defineStore第一个参数很重要,而且是唯一值。它的命名能让开发者在Devtools快速找到相关数据,方便调试

    import { defineStore } from "pinia";
    
    export const useUserStore = defineStore("main", {
      id: "app-user",
      // 相当于data
      state: () => {
        return {
          // 所有这些属性都将自动推断其类型,如果推断失败可以试下 as xxx
          counter: 0,
          name: "Eduardo",
        };
      },
      // 相当于计算属性
      getters: {
        doubleCount: (state) => {
          return state.counter * 2;
        },
      },
      // 相当于vuex的 mutation + action,可以同时写同步和异步的代码
      actions: {
        increment() {
          this.counter++;
        },
        randomizeCounter() {
          setTimeout(() => {
            this.counter = Math.round(100 * Math.random());
          }, 0);
        },
      },
    });
    
  5. HelloWorld.vue中使用

    <script setup lang="ts">
    import { ref } from "vue";
    import { Setting } from "@element-plus/icons-vue";
    //引入想要的pinia文件 {} 里面就是对应导出的名字
    import { useUserStore } from "@/store/modules/user";
    import { storeToRefs } from "pinia";
    const User = useUserStore();
    // 解构main里面的state和getters的数据,
    // 使用storeToRefs解构才有响应式,响应式可以直接修改数据,这里只用来渲染
    let { counter, name, doubleCount } = storeToRefs(User);
    defineProps<{ msg: string }>();
    
    const count = ref(0);
    //(常用方法三种)
    //常用方法一: 使用数据
    console.log(counter);
    //使用方法(方法目前不能解构)
    User.increment();
    // 常用方法二:修改数据
    counter = 9999;
    
    //常用方法三:
    //进阶使用$patch,多个修改
    const amend = () => {
      User.$patch((state) => {
        state.counter += 10;
        state.name = "张三";
      });
    };
    </script>
    
    <template>
      <h1>{{ msg }}</h1>
      <Setting />
      <div>counter:{{ counter }}</div>
      <div>doubleCount:{{ doubleCount }}</div>
      <el-button @click="User.randomizeCounter()">counter(round)</el-button>
      <el-button type="primary" @click="User.increment()">counter++</el-button>
    
      <div>{{ name }}</div>
      <el-button @click="amend()">修改</el-button>
      <div class="card">
        <button type="button" @click="count++">count is {{ count }}</button>
        <p>
          Edit
          <code>components/HelloWorld.vue</code> to test HMR
        </p>
      </div>
    
      <p>
        Check out
        <a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
          >create-vue</a
        >, the official Vue + Vite starter
      </p>
      <p>
        Install
        <a href="https://github.com/vuejs/language-tools" target="_blank">Volar</a>
        in your IDE for a better DX
      </p>
      <p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
    </template>
    
    <style scoped>
    .read-the-docs {
      color: #888;
    }
    </style>
    

    结果如图:
    在这里插入图片描述

像使用组件一样使用 SVG 图片

  1. 安装vite-svg-loader

    pnpm install -D  vite-svg-loader   -w
    
  2. vite.config.ts增加配置

    import svgLoader from "vite-svg-loader"
    
    export default defineConfig({
      plugins: [
     	svgLoader(),
      ]
    })
    
  3. 使用

    import Svg404 from "@/assets/error-page/404.svg?component";
    
    <Svg404 />
    

unocss CSS框架

  1. 安装

    pnpm install -D   unocss -w
    
  2. vue.config.js 中对Unocss进行如下配置

    import UnoCSS from "unocss/vite";
    
    export default defineConfig({
    plugins: [
        vue(),
        /** 将 SVG 静态图转化为 Vue 组件 */
        svgLoader({ defaultImport: "url" }),
        /** SVG */
        createSvgIconsPlugin({
          iconDirs: [path.resolve(process.cwd(), "src/icons/svg")],
          symbolId: "icon-[dir]-[name]",
        }),
        /** UnoCSS */
        UnoCSS(),]
    })
    
  3. main.js中按这种方式引入: import 'uno.css

    import 'uno.css
    
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值