Skip to content

Vue3.x 开发规范 - 项目指南、注释规范、Vue 规范、Git 规范、VSCode 推荐

License

Notifications You must be signed in to change notification settings

antd-templater/standard-3.x

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 

Repository files navigation

Vue3.x 开发规范


# 项目指南

项目依赖
  # 本地初始化 (生成 package.json)
  pnpm init

  # 本地安装 package.json 依赖包
  pnpm install

  # 全局安装 某个依赖包
  pnpm add -g [package]
  pnpm add -g [package]@[tag]
  pnpm add -g [package]@[version]

  # 本地安装 仅编译环境所需 依赖包
  pnpm add -D [package]
  pnpm add -D [package]@[tag]
  pnpm add -D [package]@[version]

  # 本地安装 编译及生产环境所需 依赖包
  pnpm add [package]
  pnpm add [package]@[tag]
  pnpm add [package]@[version]

  # 本地升级 某个依赖包
  pnpm upgrade [package]
  pnpm upgrade [package]@[tag]
  pnpm upgrade [package]@[version]

  # 本地移除 某个依赖包
  pnpm remove [package]

  # 本地检查 依赖包情况
  # <red>    : Major Update backward-incompatible updates --- (不建议更新)
  # <yellow> : Minor Update backward-compatible features ---- (可以更新)
  # <green>  : Patch Update backward-compatible bug fixes --- (建议更新)
  pnpm outdated

  # 本地更新 一键按需升级
  # Press <space> to select ----------------------- (空格切换选中)
  # Press <a> to toggle all ----------------------- (所有依赖选中)
  # Press <i> to invert selection ----------------- (所有依赖反选)
  # Press <Enter> install selected dependencies --- (所选依赖安装)
  pnpm up -i --latest
项目结构
  ├── .husky                               # 由 npx husky init 生成 (Git Hook 工具)
  │   ├── commit-msg                       # 规范 git message 提交和格式检查 (使用 commitlint)
  │   ├── pre-commit                       # 执行 git 提交时, 对提交源码进行检查 (使用 lint-staged)
  │
  ├── .vscode                              # VSCode 编辑器配置
  │   ├── extensions.json                  # VSCode 推荐安装的插件
  │   ├── launch.json                      # VSCode 本地开发调试配置
  │   ├── settings.json                    # VSCode 项目开发风格/格式化配置 (ESLint、Prettier等)
  │
  ├── cypress                              # Cypress 资源配置
  │   ├── downloads                        # 下载 - 资源存储区
  │   ├── fixtures                         # 定义 - 本地静态数据
  │   ├── support                          # 储存 - 测试辅助资源
  │   │   ├── commands.ts                  #  support -> 定义 自定义命令 - cy.[command]
  │   │   ├── component-index.html         #  support -> 定义 组件测试 - 首页
  │   │   ├── component.ts                 #  support -> 定义 组件测试 - 资源
  │
  ├── dist                                 # 由 pnpm build 构建的本地工程
  ├── node_modules                         # 由 pnpm install 创建的本地依赖包
  │
  ├── public                               # 静态资源 (不参与构建)
  │   ├── favicon.ico                      # 网站 favicon.ico 图标
  │   ├── logo.png                         # 网站 logo 图片, 通常在 html 模版中引用
  │   ├── msw.js                           # mock service worker (mock response)
  │
  ├── src                                  # 源代码
  │   ├── api                              # 定义与后端交互的接口
  │   │   ├── user.js                      # 示例: 规范1 - 文件名 根据后台接口 (如 /user/add 定义user)
  │   │   ├── auth.js                      # 示例: 规范2 - 文件名【 camelCase 】命名
  │   │
  │   ├── assets                           # 静态资源
  │   │   ├── logo                         # 示例: 规范1 - 分组名 根据内容进行文件夹
  │   │   │   ├── logo_light.png           # 示例: 规范2 - 文件名【 kebab_case 】命名
  │   │
  │   ├── components                       # 公共组件
  │   │   ├── BaseSearchQuery              # 示例: 建议1 - 文件名 以类型化单词开头 (如 Base)
  │   │   ├── BaseIconSelect               # 示例: 规范1 - 文件名 应倾向于完整单词而不是缩写
  │   │   ├── BaseSvgIcon                  # 示例: 规范2 - 文件名【 PascalCase 】命名
  │   │
  │   ├── configure                        # 默认配置 (建议【 default + 类型 】+【 camelCase 】命名)
  │   │   ├── defaultRouter.ts             # 预设定义 常规路由 (根路由、外部路由、异常路由、静态路由)
  │   │   ├── defaultSettings.ts           # 预设定义 前端整体 风格/主题/布局 等配置选项,在 store/app.ts 中用于初始值
  │   │   ├── presetDirective.ts           # 预设定义 Vue指令 操作权限 (示例 v-action)
  │   │   ├── presetEnvironment.ts         # 预设定义 环境变量 (源自于 .env.xxxx 配置)
  │   │   ├── presetThemeColors.ts         # 预设定义 主题色库 (例 极客蓝、拂晓蓝、薄暮)
  │   │
  │   ├── declare                          # 全局 TS 类型定义 (建议【 PascalCase 】命名)
  │   │   ├── Axios.d.ts                   # 预设定义 Axios 相关类型 (AxiosSorter ...)
  │   │   ├── Global.d.ts                  # 预设定义 JSX API / Window API 类型
  │   │   ├── ImportMeta.d.ts              # 预设定义 Vite Environment 类型
  │   │   ├── Pinia.d.ts                   # 扩展定义 pinia-plugin-persist 类型
  │   │
  │   ├── layout                           # 布局组件库
  │   │   ├── components                   # 储存仅布局组件依赖的组件
  │   │   │   ├── LayoutAvatar             # 基础布局组件 - 头像组件 Avatar
  │   │   │   ├── LayoutBreadcrumb         # 基础布局组件 - 面包屑组件 Breadcrumb
  │   │   │   ├── LayoutLogo               # 基础布局组件 - 图标栏组件 Logo
  │   │   │   ├── LayoutMultiTab           # 基础布局组件 - 多标签组件 MultiTab
  │   │   │   ├── LayoutSettingDrawer      # 基础布局组件 - 配置选项组件 SettingDrawer
  │   │   │                                #
  │   │   ├── BasicLayout.tsx              # 基础布局组件 (含 Layout.Sider、Layout.Header、Layout.Content + RouterView、Avatar ...)
  │   │   ├── BlankLayout.tsx              # 空白布局组件 (仅有 RouterView)
  │   │   ├── PageFrame.tsx                # 页面 Frame 布局组件 (适用 iframe 外部资源访问)
  │   │   ├── PageView.tsx                 # 页面/路由布局组件 (加载 Layout.Content/RouterView 对应的 Vue 组件, 指定了容器样式)
  │   │   ├── RouteView.tsx                # 页面/路由布局组件 (加载 Layout.Content/RouterView 对应的 Vue 组件, 无相关样式)
  │   │   ├── UserLayout.tsx               # 用户路由布局组件 (仅有 RouterView + 定制容器样式,一般用于用户登录页的路由)
  │   │
  │   ├── mock                             # 模拟数据交互 - (规范与api保持一致)
  │   │   ├── user                         # 示例: 用户接口
  │   │   │   ├── addUserInfo.ts           # 示例: 用户接口 - 新增
  │   │   │   ├── getUserInfoList.ts       # 示例: 用户接口 - 查询
  │   │   │                                #
  │   │   ├── setup.ts                     # 定义 setupWorker (配合 public/msw.js 实现 mock response)
  │   │
  │   ├── model                            # 数据模型 TS 类型定义 (建议【 PascalCase 】命名)
  │   │   ├── Tree.d.ts                    # 定义 Tree 树形结构模型
  │   │   ├── User.d.ts                    # 定义 User 用户信息模型
  │   │
  │   ├── plugin                           # 定义引用第三方插件
  │   │   ├── dayjs.ts                     # 导入引用 dayjs 日期插件
  │   │   ├── pinia.ts                     # 导入引用 pinia 状态管理库 (集成了 pinia-plugin-persist)
  │   │   ├── vue-ls.ts                    # 导入引用 vue-ls 储存管理
  │   │
  │   ├── router                           # 动态路由处理
  │   │   ├── generate-routes.ts           # 解析/转换/生成 动态路由 (Route)
  │   │   ├── generate-typing.d.ts         # 解析/转换/生成 类型定义
  │   │
  │   ├── store                            # pinia 状态储存 (建议【 camelCase 】命名)
  │   │   ├── app.ts                       # 定义存储 前端整体 风格/主题/布局 等配置
  │   │   ├── router.ts                    # 定义存储 Vue路由 (动态路由、静态路由、解析生成动态路由)
  │   │   ├── tag.ts                       # 定义存储 多标签页 (记录标签、缓存标签、移除标签)
  │   │   ├── user.ts                      # 定义存储 用户信息 (用户登录/退出、用户信息)
  │   │
  │   ├── styles                           # 样式定义/覆盖 (建议【 kebab_case 】命名)
  │   │   ├── customize.less               # 自定义样式 (例 flex-auto、flex-none、text-ellipsis)
  │   │   ├── normalize.less               # 重置默认样式 (关于 html、body、h1 ~ h6、p、-webkit-scrollbar)
  │   │   ├── nprogress.less               # 重写覆盖 nprogress 进度条样式
  │   │   ├── override.less                # 覆盖 ant design vue 组件样式 (目前仅覆盖 ant-drawer 部分样式)
  │   │
  │   ├── utils                            # 工具类方法 (建议【 camelCase 】命名)
  │   │   ├── common.ts                    # 定义 通用工具类 (数值四舍五入、输出指定格式的日期、取出节点文本、封装请求参数)
  │   │   ├── request.ts                   # 定义 Axios 实例 (Request拦截器、Response拦截器、预设 baseURL / timeout)
  │   │   ├── router.ts                    # 定义 layout 中 FrameView 布局组件中 提取 route link API
  │   │
  │   ├── views                            # 视图路由组件库 (建议【 PascalCase 】.vue 命名)
  │   │   ├── auth                         # 模块 - 认证管理
  │   │   │   ├── Login.vue                # 组件 - 用户登录
  │   │   │
  │   │   ├── error                        # 模块 - 异常管理
  │   │   │   ├── PageError403.vue         # 组件 - 异常 403
  │   │   │   ├── PageError404.vue         # 组件 - 异常 404
  │   │   │   ├── PageError500.vue         # 组件 - 异常 500
  │   │   │
  │   │   ├── system                       # 模块 - 系统管理
  │   │   │   ├── components               #
  │   │   │   │   ├── OrganizeManage       # 子组件库 - OrganizeManage
  │   │   │   │   ├── ResourceManage       # 子组件库 - ResourceManage
  │   │   │   │   ├── RoleManage           # 子组件库 - RoleManage
  │   │   │   │   ├── UserManage           # 子组件库 - UserManage
  │   │   │   │                            #
  │   │   │   ├── OrganizeManage.vue       # 组织管理 (路由 /system/OrganizeManage)
  │   │   │   ├── ResourceManage.vue       # 资源管理 (路由 /system/ResourceManage)
  │   │   │   ├── RoleManage.vue           # 角色管理 (路由 /system/RoleManage)
  │   │   │   ├── UserManage.vue           # 用户管理 (路由 /system/UserManage)
  │   │
  │   ├── App.vue                          # 顶层路由组件 (处理 全局 Theme/Token/Size)
  │   ├── main.less                        # 样式入口文件
  │   ├── main.ts                          # 主入口文件
  │   ├── permission.ts                    # 路由权限拦截器
  │   ├── router.constant.ts               # 配置静态路由
  │   ├── router.dynamic.ts                # 配置动态路由 (借助 vite 的 import.meta.glob 导入 src/views 目录下路由)
  │   ├── router.ts                        # 初始化 Router 实例
  │
  ├── test                                 # 测试脚本
  │   ├── cypress                          # cypress (基于浏览器运行的测试工具,主要用于测试依赖浏览器的逻辑)
  │   │   ├── -Login.vue.cy.ts             # 范例: cypress 测试 Login Vue 组件
  │   │   ├── tsconfig.json                # 定义: cypress TS 配置文件
  │   │                                    #
  │   ├── vitest                           # vitest (由 Vite 驱动的测试工具,主要用于测试不依赖浏览器的逻辑)
  │   │   ├── -utils.test.ts               # 范例: vitest 测试 Utils Api
  │   │   ├── tsconfig.json                # 定义: vitest TS 配置文件
  │
  ├── .cz-message.cjs                      # 指定 cz-message-helper 配置选项 (using by git cz)
  ├── .editorconfig                        # 指定项目的编码规范
  ├── .env                                 # 默认基础环境配置
  ├── .env.development                     # 本地开发环境配置, 会覆盖 .env 文件同名属性配置
  ├── .env.production                      # 正式运行环境配置, 会覆盖 .env 文件同名属性配置
  ├── .env.test                            # 测试运行环境配置, 会覆盖 .env 文件同名属性配置
  ├── .eslintrc-auto-import.json           # 是由 unplugin-auto-import/vite 插件自动生成 (在 eslint extends 中配置)
  ├── .gitattributes                       # 指定 git 使用的文件和路径的属性
  ├── .gitignore                           # 指定 git 哪些文件不需要添加到版本管理中
  ├── .lintstagedrc.js                     # 指定 lint-staged 配置选项
  ├── .npmignore                           # 指定 npm publish 哪些文件被忽略 (比 .gitignore 优先级高)
  ├── .npmrc                               # 指定 npm 运行时的配置选项
  ├── .prettierignore                      # 指定 prettier 哪些文件不需要校验
  ├── .prettierrc                          # 指定 prettier 格式的规则配置
  ├── .release-it.json                     # 指定 release-it 配置选项
  ├── auto-imports.d.ts                    # 是由 unplugin-auto-import/vite 插件自动生成
  ├── commitlint.config.js                 # 指定 @commitlint/cli、@commitlint/config-conventional 的配置选项
  ├── components.d.ts                      # 是由 unplugin-vue-components/vite 插件自动生成
  ├── eslint.config.mjs                    # 指定 eslint 校验的规则配置
  ├── cypress.config.ts                    # Cypress 配置文件
  ├── index.html                           # 编译构建所需的 html 模版文件
  ├── LICENSE                              # 前端项目许可文件
  ├── package.json                         # 前端项目配置文件
  ├── pnpm-lock.yaml                       # pnpm 安装依赖包版本锁定文件
  ├── README.md                            # 前端项目介绍文件
  ├── tsconfig.json                        # typescript 配置文件
  ├── vite.config.ts                       # Vite 配置文件 (dev server / run build)
  ├── volar.config.js                      # Volar 配置文件 (配合 volar-service-prettyhtml 插件)

# 注释规范

文档注释 -- 常用于文件的摘要描述
<!--
  * 404 页面
  * lin pengteng
  * 2024-04-03
-->
<template>
  <a-result title="404页面">
    <template #extra>
      <a-button>返回首页</a-button>
    </template>
  </a-result>
</template>
import T from 'ant-design-vue/es/table/Table'

/**
 * 表格组件
 * lin pengteng
 * 2024-04-03
 */
export default defineComponent({
  name: 'BaseTable',
  props: {
    ...T.props,
  },
  setup(props) {
    // ...
  },
})
/**
 * 规范标签默认样式
 * lin pengteng
 * 2024-04-03
 */
html,
body,
#app,
#root {
  height: 100%;
}
方法注释 -- 常用于函数的摘要描述
import moment from 'moment'

/**
 * 根据格式转换 日期
 * lin pengteng
 * 2024-04-03
 */
export const takeTimeToDate = (date: Date | string | number, format?: string) => {
  if (date) {
    try {
      return moment(date, format)
    } catch {}
  }
  return null
}
多行注释 -- 常用于字段、逻辑、注解等多行描述
/* 
  这是一个临时储存区
  记录用户操作过的用户ID
 */
const CACHES = []
单行注释 -- 常用于字段、逻辑、注解等单行描述
import * as VueTypes from 'vue-types'

export default defineComponent({
  name: 'CustomButton',
  props: {
    // 按钮图标
    icon: VueTypes.string().def('filter'),
    // 按钮类型
    type: VueTypes.string().def('default'),
  },
  setup(props) {
    // ...
  },
})

# Vue 规范

组件顶级元素的顺序 (必要)
  • templatescriptstyle 顺序必须一致,之间空一行隔开

    <template>
      <section class="container">
        <AButton>自定义</AButton>
      </section>
    </template>
    
    <script setup lang="ts">
      defineOptions({
        name: 'CustomButton',
      })
    </script>
    
    <style lang="less" scoped>
      .container {
        width: 100%;
        height: auto;
      }
    </style>
组件名由多个单词组成 (必要)
  • 这样做可以避免跟现有以及未来 HTML 元素相冲突,因为所有的 HTML 元素名称都是单个单词的

    // Bad
    export default defineComponent({
      name: 'Todo',
      // ...
    })
    
    // Good
    export default defineComponent({
      name: 'TodoComponent',
      // ...
    })
组件名应为完整单词而非缩写 (必要)
  • 编辑器中自动补全已经让书写长命名的代价非常之低,而其带来的明确性却是非常宝贵的

      # Bad
      components/
        |- SdSettings.vue
        |- UProOpts.vue
    
      # Good
      components/
        |- StudentDashboardSettings.vue
        |- UserProfileOptions.vue
组件名中单词顺序按语境排序 (必要)
  • 组件名应该以高级别的(通常是一般化描述的)单词开头,以描述性的修饰词结尾,组件间排序关系一目了然

      # Bad
      components/
        |- ClearSearchButton.vue
        |- RunSearchButton.vue
    
      # Good
      components/
        |- SearchButtonClear.vue
        |- SearchButtonRun.vue
高耦合子组件名以父组件名为前缀 (必要)
  • 如果一个组件只在某个父组件的场景下有意义,这层关系应该体现在其名字或目录上

      # Bad
      components/
        |- TodoList.vue
        |- TodoItem.vue
        |- TodoButton.vue
    
      # Good
      components/
        |- TodoList.vue
        |- TodoListItem.vue
        |- TodoListItemButton.vue
    
      # Good
      components/
        |- TodoList/
        |- |- index.vue
        |- |- Item.vue
        |- |- ItemButton.vue
单文件组件文件名应 PascalCase 命名 (必要)
  • 单文件组件的文件名应该始终是单词大写开头 PascalCase

      # Bad
      components/
        |- mycomponent1.vue
        |- myComponent2.vue
        |- Mycomponent3.vue
        |- my-component4.vue
    
      # Good
      components/
        |- MyComponent1.vue
        |- MyComponent2.vue
        |- MyComponent3.vue
        |- MyComponent4.vue
.vue 单文件模板应该只包含简单的表达式 (必要)
  • 组件模板应该只包含简单的表达式,复杂的表达式则应该重构为计算属性或方法

    <!-- Bad -->
    <template>
      <div class="container">{{ fullName.split(' ').map(function (word) { return word[0].toUpperCase() + word.slice(1) }).join(' ') }}</div>
    </template>
    
    <script setup lang="ts">
      import { ref } from 'vue'
    
      const fullName = ref('todo component')
    </script>
    
    <!-- Good -->
    <template>
      <div class="container">{{ computedFullName }}</div>
    </template>
    
    <script setup lang="ts">
      import { ref, computed } from 'vue'
    
      const fullName = ref('todo component')
    
      const computedFullName = computed(() => {
        const names = fullName.value.split(' ')
        return names.map(word => word[0].toUpperCase() + word.slice(1)).join(' ')
      })
    </script>
.vue 单文件的自闭合组件应省略闭合标签 (必要)
  • 自闭合组件表示它们不仅没有内容,没有了额外的闭合标签,代码也更简洁

    <!-- Bad -->
    <template>
      <MyComponent></MyComponent>
    </template>
    
    <!-- Good -->
    <template>
      <MyComponent />
    </template>
.html 文件的自闭合组件不能省略闭合标签 (必要)
  • HTML 并不支持自闭合的自定义元素——只有官方的“空”元素

    <!-- Bad -->
    <body>
      <div />
    </body>
    
    <!-- Good -->
    <body>
      <div></div>
    </body>
.vue 单文件的组件以 PascalCase 方式引用 (必要)
  • 采用 PascalCase 风格,具有较高可读性,同时避免跟现有的以及未来的 HTML 元素相冲突

    <!-- Bad -->
    <template>
      <new-component />
    </template>
    
    <script>
      import NewComponent from 'NewComponent'
    </script>
    
    <!-- Good -->
    <template>
      <NewComponent />
    </template>
    
    <script>
      import NewComponent from 'NewComponent'
    </script>
.jsx/.tsx 文件的组件以 PascalCase 方式使用 (必要)
  • 使得代码的读者更容易分辨 Vue 组件和 HTML 元素

      // Bad
      <script lang="ts">
      import NewComponent from 'NewComponent'
    
      export default defineComponent({
        name: 'TodoComponent',
        render () {
          return () => <new-component>
        }
      })
      </script>
    
      // Good
      <script lang="ts">
      import NewComponent from 'NewComponent'
    
      export default defineComponent({
        name: 'TodoComponent',
        render () {
          return () => <NewComponent>
        }
      }
      </script>
组件多个 attribute 应该分多行撰写 (必要)
  • 组件多个 attribute 元素每个一行,更具可读性

      // Bad
      <script lang="ts">
      import NewComponent from 'NewComponent'
    
      export default defineComponent({
        name: 'TodoComponent',
        render () {
          return () => <NewComponent type="button" color="#f34d4d">
        }
      })
      </script>
    
      // Good
      <script lang="ts">
      import NewComponent from 'NewComponent'
    
      export default defineComponent({
        name: 'TodoComponent',
        render () {
          return () => (
            <NewComponent
              type="button"
              color="#f34d4d"
            >
          )
        }
      }
      </script>
组件的 Prop 定义尽量详细 (必要)
  • prop 定义尽量详细,至少需要指定类型,如果提供不正确的 prop,Vue 会帮助你捕获错误

    // Bad
    export default defineComponent({
      props: ['status'],
    })
    
    // Good
    import { PropType } from 'vue'
    
    export default defineComponent({
      props: {
        status: {
          type: String as PropType<string>,
          default: '',
        },
      },
    })
    
    // Good
    import * as VueTypes from 'vue-types'
    
    export default defineComponent({
      props: {
        status: VueTypes.string().def(''),
      },
    })
    
    // Good
    <script setup lang="ts">
    export interface Props {
      status?: string
    }
    
    const props = defineProps<Props>()
    </script>
组件的 Prop 名应为驼峰式 (必要)
  • 在声明 prop 及 模板和 JSX 使用时,其命名应使用 camelCase

    <!-- Bad -->
    <template>
      <welcome-message :greeting-text="greetingText" />
    </template>
    
    <script>
      export default defineComponent({
        name: 'WelcomeMessage',
        props: {
          'greeting-text': VueTypes.string().def(''),
        },
      })
    </script>
    
    <!-- Good -->
    <template>
      <WelcomeMessage :greetingText="greetingText" />
    </template>
    
    <script lang="ts">
      export default defineComponent({
        name: 'WelcomeMessage',
        props: {
          greetingText: VueTypes.string().def(''),
        },
      })
    </script>
    
    <!-- Good -->
    <template>
      <WelcomeMessage :greetingText="greetingText" />
    </template>
    
    <script setup lang="ts">
      export interface Props {
        greetingText?: string
      }
      defineProps<Props>()
    </script>
避免将 v-if 和 v-for 用在一起 (必要)
  • 为了不渲染本应该隐藏的列表, 则可将 v-if 移动至其父容器元素上

    <!-- Bad -->
    <ul>
      <li v-for="user in users" v-if="shouldShowUsers" :key="user.id">{{ user.name }}</li>
    </ul>
    
    <!-- Good -->
    <ul v-if="shouldShowUsers">
      <li v-for="user in users" :key="user.id">{{ user.name }}</li>
    </ul>
  • 根据某属性过滤列表中的项目, 则可替换为一个计算属性, 让其返回过滤后的列表

    <!-- Bad -->
    <ul>
      <li v-for="user in users" v-if="user.isActive" :key="user.id">{{ user.name }}</li>
    </ul>
    
    <!-- Good -->
    <ul>
      <li v-for="user in activeUsers" :key="user.id">{{ user.name }}</li>
    </ul>
必须为 v-for 设置键值 key (必要)
  • 在组件上总是必须用 key 配合 v-for,以便维护内部组件及其子树的状态

    <!-- Bad -->
    <ul>
      <li v-for="todo in todos">{{ todo.text }}</li>
    </ul>
    
    <!-- Good -->
    <ul>
      <li v-for="todo in todos" :key="todo.id">{{ todo.text }}</li>
    </ul>
应为组件样式设置作用域 (必要)
  • 基于有作用域的样式可以避免与其他组件的样式发生冲突

    <!-- Bad -->
    <template>
      <button class="btn btn-close">X</button>
    </template>
    
    <style>
      .btn-close {
        background-color: red;
      }
    </style>
    
    <!-- Good -->
    <template>
      <button class="btn btn-close">X</button>
    </template>
    
    <style scoped>
      .btn-close {
        background-color: red;
      }
    </style>
组件/实例各指令采用简写 (推荐)
  • 用 : 表示 v-bind: , @ 表示 v-on: , # 表示 v-slot:

    <!-- Bad -->
    <template>
      <div class="container">
        <template v-slot:header>
          <h1>A page title</h1>
        </template>
        <input v-bind:value="newValue" v-on:input="onInput" />
      </div>
    </template>
    
    <!-- Good -->
    <template>
      <div class="container">
        <template #header>
          <h1>A page title</h1>
        </template>
        <input :value="newValue" @input="onInput" />
      </div>
    </template>
组件/实例的选项顺序 (推荐)
  • 组件/实例的选项应该有统一的顺序

      # 副作用 (触发组件外的影响)
      el
    
      # 全局感知 (要求组件以外的知识)
      name
      parent
    
      # 组件类型 (更改组件的类型)
      functional
    
      # 模板修改器 (改变模板的编译方式)
      delimiters
      comments
    
      # 模板依赖 (模板内使用的资源)
      components
      directives
      filters
    
      # 组合 (向选项里合并 property)
      extends
      mixins
    
      # 接口 (组件的接口)
      inheritAttrs
      model
      props/propsData
    
      # 本地状态 (本地的响应式 property)
      data
      computed
    
      # 监听事件 (通过响应式事件触发的回调)
      watch
    
      # 生命周期钩子 (按照它们被调用的顺序)
      beforeCreate
      created
      beforeMount
      mounted
      beforeUpdate
      updated
      activated
      deactivated
      beforeDestroy
      destroyed
    
      # 非响应式的 property
      methods
    
      # 渲染 (组件输出的声明式描述)
      template/render
      renderError
组件/实例的属性顺序 (推荐)
  • 组件/实例的属性应该有统一的顺序

      # 引用 (提供组件的引用)
      is
      id
      ref
    
      # 双向绑定 (把绑定和事件结合起来)
      v-model
    
      # 列表渲染 (创建多个变化的相同元素)
      v-for
    
      # 条件渲染 (元素是否渲染/显示)
      v-if
      v-else-if
      v-else
      v-show
      v-cloak
    
      # 其他属性 (attribute 或 prop)
      key
      ...
    
      # 渲染方式 (改变元素的渲染方式)
      v-pre
      v-once
      v-html
      v-text
    
      # 事件 (组件事件监听器)
      v-on

# Git 规范

Git 分支设计 (推荐)
  • 基于如下四种常用系统开发环境,而设计的 Git 五种分支类型

    • PRO 环境:用于生产环境

    • DEV 环境:用于开发者调试使用

    • FAT 环境:功能验收测试环境,用于测试环境下的测试人员测试使用

    • UAT 环境:生产预发布环境,用于生产环境下的测试人员测试使用


      分支 名称 命名规范 运行环境
      master 主分支 / PRO
      release 预上线分支 / UAT
      develop 测试分支 / FAT
      feature 需求开发分支 feat-xxx DEV
      hotfix 紧急修复分支 fix-xxx DEV

      # master 分支
      a. master 为主分支,用于部署到正式环境(PRO)
      b. 一般由 release 分支合并,任何情况下不允许直接在 master 分支上修改代码
    
      # release 分支
      a. release 为预上线分支,用于部署到预上线环境(UAT)始终保持与 master 分支一致
      b. 一般由 develop 或 hotfix 分支合并,不建议直接在 release 分支上直接修改代码
      c. 如果在 release 分支测试出问题,需要回归验证 develop 分支看否存在此问题
    
      # develop 分支
      a. develop 为测试分支,用于部署到测试环境(FAT),始终保持最新完成以及 bug 修复后的代码
      b. 可根据需求大小程度确定是由 feature 分支合并,还是直接在上面开发
      c. 一定是满足测试的代码才能往上面合并或提交。
    
      # feature 分支
      a. feature 为需求开发分支,命名规则为【 feat- 】开头,一旦该需求上线,分支本地预留 3-7 天后将其删除
    
      # hotfix 分支
      a. hotfix 为紧急修复分支,命名规则为【 fix- 】开头
      b. 当线上出现紧急问题需要马上修复时,需要基于 release 或 master 分支创建 hotfix 分支
      c. 修复完成后,再合并到 release 或 develop 分支,一旦修复上线,分支本地预留 1-3 天后将其删除
Git 版本号规范 (推荐)
  • 版本号 Tag 采用三段式,v 版本.里程碑.序号,如:v1.0.0
      修改第1位 - 架构升级或架构重大调整
      修改第2位 - 新功能上线或者模块大的调整
      修改第3位 - bug修复上线、需求完善等调整
Git Commit 规范介绍 (重要)
  • 目前社区流行的 commit 规范(来自于 Angular 团队的 commit 规范)

      # Commit Message 的三个部分:Header,Body 和 Footer, 注意两两之前空行间隔
      <type>(<scope>): <subject>
      <BLANK LINE>
      <body>
      <BLANK LINE>
      <footer>
    
      # Commit Message 之 Header 部分
      type(必需)--- 用于说明 commit 的类别
        a. init: 初始化
        b. feat: 新增feature
        c. fix: 修复bug
        d. docs: 仅仅修改了文档,如readme.md
        e. style: 仅仅是对格式进行修改,如逗号、缩进、空格等。不改变代码逻辑
        f. refactor: 代码重构,没有新增功能或修复bug
        g. perf: 优化相关,如提升性能、用户体验等
        h. test: 测试用例,包括单元测试、集成测试
        i. chore: 改变构建流程、或者增加依赖库、工具等
        j. revert: 版本回滚
        k. merge:代码合并
        l. sync:同步分支
    
      scope(可选)--- 用于说明 commit 影响范围,可以通过 src 名下文件夹定义,例如
        a. all or *
        b. api
        c. components
        d. utils
        e. views
        f. ...
    
      subject(必需)--- commit 内容的简短描述,不超过70个字符
    
    
      # Commit Message 之 Body 部分(可选)
      a. 对本次 commit 修改内容的具体描述, 可以分为多行
      b. 描述为什么修改, 做了什么样的修改, 以及开发的思路等等
    
    
      # Commit Message 之 footer 部分(可选,仅处理 不兼容 或 关闭 Issue使用)
      a. 处理当前代码与上个版本不兼容, 以 BREAKING CHANGE: 开头进行详细描述
      b. 当前 commit 关闭 issue,如 Closes #123, #245, #992
  • 基于社区流行的 commit Message 示范

      # Commit Message - Header + Body
      init: Vue3.x 开发规范首次提交
    
      a. 包含了项目指南、注释规范、Vue 规范、Git规范
      b. 目前支持了 Vue3.x, 兼容 Vue2.x
    
    
      # Commit Message - 仅 Header
      docs(README.md): Vue3.x 开发规范完善 VSCode 开发等
Git Commit 规范校验 (推荐)
  • 安装依赖

      pnpm add husky lint-staged @commitlint/cli @commitlint/config-conventional -D
  • 初始化 husky (会在项目根目录下生成 .husky)

      npx husky init
  • 在 .husky 名下 新增 commit-msg、pre-commit 两个 Git Hook

      # commit-msg 内容如下:
      # npx --no-install commitlint --edit $1
    
      # pre-commit 内容如下:
      # npx lint-staged
  • 指定 commitlint 配置选项 (commitlint.config.js)

    module.exports = {
      extends: ['@commitlint/config-conventional'],
      rules: {
        'type-enum': [2, 'always', ['fix', 'feat', 'begin', 'docs', 'style', 'refactor', 'chore', 'perf', 'test', 'merge', 'revert', 'wip']],
        'type-case': [0],
        'scope-case': [0],
        'subject-case': [0],
        'header-case': [0],
        'body-case': [0],
        'type-empty': [2, 'never'],
        'scope-empty': [0],
        'subject-empty': [2, 'never'],
        'body-empty': [0],
        'subject-full-stop': [0],
        'header-full-stop': [0],
        'body-full-stop': [0],
        'header-max-length': [2, 'always', 72],
        'body-leading-blank': [2, 'always'],
        'footer-leading-blank': [2, 'always'],
      },
    }
  • 指定 lint-staged 配置选项 (.lintstagedrc.js)

    module.exports = {
      'src/**/*.{js,jsx,ts,tsx,vue}': ['eslint --fix'],
    }
Git Commit 辅助工具 (推荐)
  • 安装依赖

      # 全局安装 commitizen
      pnpm add commitizen -g
    
      # 本地安装 cz-message-helper
      pnpm add cz-message-helper -D
  • 在 package.json 指定 commitizen、cz-message-helper 配置

    {
      "name": "@antd-templater/template-3.x",
      "description": "后台管理系统模版 - 基于 Vue3.x Ant Design Vue 组件库",
    
      "config": {
        "cz-message-helper": {
          "config": ".cz-message.cjs"
        },
        "commitizen": {
          "path": "node_modules/cz-message-helper"
        }
      }
    }
  • 创建 cz-message-helper 配置文件 .cz-message.cjs

    /**
     * Commit message helper for commitizen
     * https://github.com/linpengteng/cz-message-helper
     */
    module.exports = {
      language: 'cn', // 支持 en | cn
    }
  • 如何使用 cz-message-helper (using by git cz)

    cz-message-helper


# VSCode 推荐

常用插件推荐
  • 基于功能性分类: Git 分支管理、代码智能提示、校验优化代码

      # Git分支管理
      name:        GitLens — Git supercharged
      author:      GitKraken
      description: 增强内置的 Git 功能, 一目了然地可视化代码作者身份, 无缝导航和探索 Git 存储库等等
    
    
      # 代码智能提示
      name:        Vue 3 Snippets
      author:      hollowtree
      description: Vue2.x 和 Vue3.x 代码片段智能提示
    
    
      # 校验优化代码
      name:        ESLint
      author:      Dirk Baeumer
      description: 将 ESLint JavaScript 集成到 VSCode 中
      attention:   需要 pnpm install 相关依赖
    
      name:        Prettier - Code formatter
      author:      Prettier
      description: 使用 prettier 格式化代码
      attention:   需要 pnpm install 相关依赖
    
      name:        Vue - Official
      author:      Vue (vuejs.org)
      description: 官方为Vue构建的语言支持扩展
    
项目开发配置
  • 项目根目录下建立 .vscode/settings.json 文件,统一开发配置

    {
      "[css]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
      },
      "[less]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
      },
      "[scss]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
      },
      "[stylus]": {
        "editor.defaultFormatter": "thisismanta.stylus-supremacy"
      },
      "[html]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
      },
      "[javascript]": {
        "editor.defaultFormatter": "dbaeumer.vscode-eslint"
      },
      "[typescript]": {
        "editor.defaultFormatter": "dbaeumer.vscode-eslint"
      },
      "[jsonc]": {
        "editor.defaultFormatter": "vscode.json-language-features"
      },
      "[json]": {
        "editor.defaultFormatter": "vscode.json-language-features"
      },
      "[vue]": {
        "editor.defaultFormatter": "dbaeumer.vscode-eslint"
      },
      "editor.codeActionsOnSave": {
        "source.fixAll": "explicit"
      },
      "editor.tabSize": 2,
      "editor.formatOnSave": true,
      "editor.formatOnPaste": true,
      "editor.detectIndentation": false,
      "editor.renderControlCharacters": true,
      "eslint.useFlatConfig": true,
      "eslint.format.enable": true,
      "eslint.probe": ["javascript", "javascriptreact", "typescriptreact", "typescript", "html", "wxml", "vue"],
      "prettier.semi": false,
      "prettier.useTabs": false,
      "prettier.tabWidth": 2,
      "prettier.printWidth": 200,
      "prettier.singleQuote": true,
      "prettier.bracketSpacing": true,
      "prettier.bracketSameLine": false,
      "prettier.jsxSingleQuote": false,
      "prettier.vueIndentScriptAndStyle": false,
      "prettier.htmlWhitespaceSensitivity": "ignore",
      "prettier.quoteProps": "consistent",
      "prettier.arrowParens": "avoid",
      "prettier.trailingComma": "es5"
    }
项目脚本指令
  • 命令行 Prettier 一键格式化,需 .prettierignore.prettierrc 配置

      npx prettier --write --loglevel warn "src/**/*.vue"
  • 命令行 ESlint 一键校验并格式化,需 eslint.config.mjs 配置

      npx eslint --fix --quiet src/**/*{.vue,.tsx,.ts}

About

Vue3.x 开发规范 - 项目指南、注释规范、Vue 规范、Git 规范、VSCode 推荐

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published