vue3项目经验分享

lxf2023-03-15 07:30:02

前言

初衷

在这里分享一下公司自己的vue3项目从0到1创建的过程,包括其中遇到的一些问题和解决方式,以及一些能够提高我们开发效率的小技巧。如果又不好或者可以改进的地方,欢迎大家指正。

使用背景

当时还没有出vu3.1的版本,出于稳定性考虑,当时使用的是vue3.0.0版本,当时是觉得这个版本兼容了2.x的写法(当然我们都是推荐是3的写法,对于没有接触过3.x版本的开发同学会更友好,让他们能有一个慢慢适应过程。)

项目介绍

包管理工具

  • 建议使用 yarn,也是 vue-cli4.0+ 默认工具(我用的是@vue/cli 4.5.13)

主要用到的库

  • vue 全家桶 vue3 + vue-router + vuex + typescript + ant-design-vue + less
  • http 请求:axios
  • ui 库:ant-design-vue
  • 提交规范:git cz commitizen
  • 版本更改历史: changelog(暂无)
  • 代码检查:eslint+eslint-typescript,格式化:prettier.
  • webpack 插件:terser-webpack-plugin(压缩文件)webpack-bundle-analyzer(打包文件分析)
  • 数据持久化:使用vuex-persistedstate包实现数据持久化

代码基础架构说明

|-- 根目录
    
    |-- dist 项目 build 之后的文件夹
    |-- public 项目静态资源,不经过 webpack,以及默认的模版,适合存放第三方压缩好的资源
    |-- src 主要的开发目录
    | |-- @types 项目共用的 type
    | |-- App.vue 页面渲染根节点
    | |-- main.ts 入口文件
    | |-- shims-vue.d.ts vue 文件类型的 type
    | |-- services http 请求相关
    | | |-- config  请求配置相关
    | | | |-- axios.ts 业务请求封装
    | | | |-- download.ts 文件下载方法封装
    | | | |-- plugin.ts 相关插件封装
    | | | |-- prefix.ts 静态网关头配置
    | | |-- modules  各个模块请求接口配置
    | | | |-- moduleA  A模块接口
    | | | |-- moduleB  B模块接口
    | |-- assets 存放静态资源,这个文件夹下的文件会走 webpack 压缩流程
    | |-- components
    | | |-- global 全局组件放在这里 最好按功能类型划分文件夹(配置了子文件夹一会递归全局注册)
    | | |-- index.ts 全局组件自动注册脚本
    | |-- config 全局静态配置
    | |-- layout 页面页面骨架
    | |-- plugins 存放第三方插件
    | | |-- index.ts 插件挂载入口
    | | |-- antd.ts antd组件注册入口
    | |-- router 路由
    | | |-- index.ts 路由入口
    | | |-- ... 其他模块路由配置,会自动装载
    | |-- store vuex
    | | |-- modules 多个模块
    | | |-- index.ts 自动装载模块
    | | |-- app app 模块
    | |-- styles 全局样式, ui 库主题样式
    | | |-- antd.less
    | | |-- reset.less
    | | |-- index.less
    | | |-- normalize.css 标准化各个浏览器差异
    | | |-- var.less 主题配置文件
    | |-- utils 常用函数以及其他有用工具
    | | |-- common.ts
    | |-- views 页面级组件
    | |-- Home.vue 正常页面
    | |-- Test.vue
    |-- .env.development 开发环境配置
    |-- .env.preview 测试环境配置
    |-- .env.production 生产环境配置
    |-- .eslintignore eslint 要忽略的文件夹
    |-- .eslintrc.js eslint 规则配置
    |-- .gitignore git 忽略的文件
    |-- .prettierrc.js 格式化插件配置 可以按照公司规范定制
    |-- README.md 项目说明
    |-- .cz-config 自定义git-commit配置信息
    |-- babel.config.js babel 设置 (包含Ui框架的按需引入配置)
    |-- global.d.ts 全局的 type
    |-- package.json npm 配置
    |-- tsconfig.json typescript 配置
    |-- typedoc.json 文档配置文件
    |-- vue.config.js vue-cli 脚手架配置文件

项目架构github地址:github.com/XiaoRIGE/vu… 该项目开箱即用,如果对你有帮助,欢迎star

项目中的一些小技巧分享

配置全局主题样式

依赖的包是 style-resources-loader、vue-cli-plugin-style-resources-loader,目的是为了在单文件中使用时不再需要每次都去做引入操作。

    • 安装对应的依赖
    yarn add style-resources-loader vue-cli-plugin-style-resources-loader --dev
    或者
    npm i style-resources-loader vue-cli-plugin-style-resources-loader --save-dev
    • vue.config.js中配置
 pluginOptions: {
    "style-resources-loader": {
      preProcessor: "less",
      patterns: ["./src/styles/var.less"],
    },
  },
    • 重启项目,文件中使用变量文件

vue3项目经验分享

自动化注册(批处理脚本)

首先你得知道这个函数,以及对应的参数含义,了解了之后你大概也能知道他能帮我们做什么了。

require.context(directory,useSubdirectories,regExp)

  • directory:表示检索的目录
  • useSubdirectories:表示是否检索子文件夹
  • regExp:匹配文件的正则表达式,一般是文件名

使用require.context实现一些自动注册脚本,减少重复劳动,比如:

  1. 批量引入并注册组件(只要将组件放在components文件夹内,就能实现自动注册),全局注册组件也是同理。
<template>
  <div class="test">
    <h1>test</h1>
    <Component-A />
    <Component-B />
    <Component-C />
  </div>
</template>

<script lang="ts">
const path = require("path");
const files = require.context("./components", false, /\.vue$/);
const modules: any = {};
files.keys().forEach((key) => {
  const name = path.basename(key, ".vue");
  modules[name] = files(key).default || files(key);
});

import { defineComponent } from "vue";
export default defineComponent({
  name: "test",
  components: modules,
  setup() {
    return {};
  },
});
</script>

<style lang="less" scoped>
.test {
}
</style>
  1. 动态引入vuex的module
const files = require.context('.', true, /\.ts$/);
const modules: any = {};

files.keys().forEach(key => {
  if (key === './index.ts') return;
  const path = key.replace(/(\.\/|\.ts)/g, '');
  const [namespace, imported] = path.split('/');
  if (!modules[namespace]) {
    modules[namespace] = {
      namespaced: true,
    };
  }
  modules[namespace][imported] = files(key).default;
});

export default modules;

对应的目录结构如下

vue3项目经验分享 当然,项目中还有很多地方可以举一反三的,能够帮我们省去很多重复操作的时间。

vuex使用方法升级

通过对module中模块写法进行统一,然后使用工具函数实现统一操作

  1. 首先上目录结构如下

vue3项目经验分享

  1. 配置工具函数
/**
 * @description setStoreState -方法是一个 mutaitions 的操作
 * @type {T} T - 你要更改的模块的类型
 * @param {string}  module - 要操作的state 的 module 名
 * @param {string}  key - 要操作的state 的 module 下的 key 值
 * @param {any} value - 当有 msg 参数时,视为赋值操作,触发 mutation,msg 则为要复制的数据.
 * @example 如果需要更改 app 模块下的 theme为 dark,这样使用:setStoreState('app','theme','dark')
 * @example 目前只支持更改 module 的 state 第一层,不支持单独修改深层嵌套的 key,如需更改,请直接替换第一层的对象
 *  如
 *   ``` const state = {
 *                 name: {
 *                   firstName:'jack',
 *                   lastName:'Ma'
 *                 }
 *               }
 *   ```
 *  想要单独修改 firstName,直接使用 setStoreState<AppStateType>('app','name',{firstName:'modifiedName',lastName:'Ma'})
 */
export const setStoreState = function setStoreState<T>(
  module: ModuleNameType,
  key: keyof T,
  value: any
) {
  store.commit({
    type: `${module}/__set`,
    key,
    val: value
  });
};

/**
 * @description 封装 dispatch 方法
 * @type {T} T  你要派发actions的模块的类型
 * @example 使用方法如下  const result = await dispatchActions<UserActionsType>('console','refreshToken',1)
 */
export const dispatchAction = function dispatchAction<T>(
  module: ModuleNameType,
  key: keyof T,
  value?: any
) {
  store.dispatch(`${module}/${key}`, value);
};

/**
 * @description 封装 dispatch 方法
 * @type {T} T  你要获取 getters的模块的类型
 * @example 使用方法如下  const result =  getStoreGetter<ConsoleGetterType>('console','list')
 */
export const getStoreGetter = function getStoreGetter<T>(
  module: ModuleNameType,
  key: keyof T
) {
  return store.getters[`${module}/${key}`];
};

配置commit规范

在一个开发团队中,前端开发的代码管理越来越规范化、工程化,而代码commit更是需要一个统一的规范去约束,保证代码commit时的规范性。尤其多人参与一个项目开发时,大家的代码commit风格不相同,不便于后续的代码统一管理和可读性;所以良好的git commit风格是很重要的。在这里就介绍几个我们项目中使用到的工具

依赖介绍

  1. commitlint 很多时候我们提交代码时,运行 git commmit -m 'xxx' 即可,而commitlint可以对message进行约束,是判断message是否符合格式要求的工具。commitlint 推荐结合config-conventional 配置使用,正确的提交格式是: git commit -m <type>[optional scope]: <description>

  2. commitizen+cz-customizable commitizen是规范commit message的工具,提供选择的commit message类型,快速生成commit message说明;而cz-customizable作为它的适配器,可以定制提交说明信息的type。

  3. husky + lint-staged 进行代码质量规范检查时,husky可以阻止不符合规范的commit,push等操作,husky是注册在git pre-commit钩子函数被调用时执行lint-staged,pre-commit 钩子在git commit 时就会触发。lint-staged对暂存区中有改动的文件根据ESLint 和 Prettier的规则进行检测;eslint+husky+prettier+lint-staged工具的配合使用可以规范我们的代码格式统一,进行代码格式检查 和代码美化,保证代码质量。

配置步骤

  1. 安装commitlint
npm install  @commitlint/cli @commitlint/config-conventional  -D

在根目录下新建.commitlintrc.js或者commitlint.config.js文件

module.exports = {
    extends: ['@commitlint/config-conventional']
};
  1. 安装commitizen+cz-customizable
npm install commitizen cz-customizable -D

在根目录下新建.cz-config.js文件,配置commit type。

// 相关配置:https://github.com/leoforfree/cz-customizable
module.exports = {
    types: [
        {
            value: 'feat',
            name: '✨ feat(新功能)'
        },
        {
            value: 'fix',
            name: '