目录
代码规范是一个非常重要的事情 ,很多企业都有自己的代码规范体系 ,
而在不同阶段体系 HTML 、CSS、JS 也有代码规范 !
那么到了后期框架和库阶段规范你知道吗 ?
今天为大家分享一组热门框架 VUE 的代码风格规范指南
市面上常用的命名规范 :
1.1.1 项目名
全部采用小写方式,以 短横线 分隔 ,
例 : my-project-name web-gsp-pc
1.1.2 目录名
参照项目命名规则,有复数结构时,要采用复数命名法,
例 :docs、assets、components、directives、mixins、utils、views


- my-project-name/
- |- BuildScript // 流水线部署文件目录
- |- docs // 项目的细化文档目录(可选)
- |- nginx // 部署在容器上前端项目 nginx 代理文件目录
- |- node_modules // 下载的依赖包
- |- public // 静态页面目录
- |- index.html // 项目入口
- |- src // 源码目录
- |- api // http 请求目录
- |- assets // 静态资源目录,这里的资源会被wabpack构建
- |- icon // icon 存放目录
- |- img // 图片存放目录
- |- js // 公共 js 文件目录
- |- scss // 公共样式 scss 存放目录
- |- frame.scss // 入口文件
- |- global.scss // 公共样式
- |- reset.scss // 重置样式
- |- components // 组件
- |- directives // 指令
- |- mixins // 混入
- |- plugins // 插件
- |- router // 路由
- |- routes // 详细的路由拆分目录(可选)
- |- index.js
- |- store // 全局状态管理
- |- utils // 工具存放目录
- |- request.js // 公共请求工具
- |- views // 页面存放目录
- |- App.vue // 根组件
- |- main.js // 入口文件
- |- tests // 测试用例
- |- .browserslistrc// 浏览器兼容配置文件
- |- .editorconfig // 编辑器配置文件
- |- .eslintignore // eslint 忽略规则
- |- .eslintrc.js // eslint 规则
- |- .gitignore // git 忽略规则
- |- babel.config.js // babel 规则
- |- Dockerfile // Docker 部署文件
- |- jest.config.js
- |- package-lock.json
- |- package.json // 依赖
- |- README.md // 项目 README
- |- vue.config.js // webpack 配置
1.1.3、图像文件名
全部采用 小写 方式,优先选择 单个单词 命名,
多个单词命名以 下划线 _ 分隔

- banner_sina.gif
- menu_aboutus.gif
- menutitle_news.gif
- logo_police.gif
- logo_national.gif
- pic_people.jpg
- pic_TV.jpg
1.1.4、HTML 文件名
全部采用 小写 方式,优先选择 单个单词 命名,
多个单词命名以 下划线 _ 分隔

- |- error_report.html
- |- success_report.html
1.1.5、CSS 文件名
全部采用 小写 方式,优先选择 单个单词 命名,
多个单词命名以 短横线 - 分隔

- |- normalize.less
- |- base.less
- |- date-picker.scss
- |- input-number.scss
1.1.6、JavaScript 文件名
全部采用 小写 方式,优先选择 单个单词 命名,
多个单词命名以 短横线 - 分隔

- |- index.js
- |- plugin.js
- |- util.js
- |- date-util.js
- |- account-model.js
- |- collapse-transition.js
上述规则可以 快速记忆 为
“ 静态文件 下划线 _ ,编译文件 短横线 - ”
推荐观看文章 :
Vue项目组件注册命名规范_雨季mo浅忆的博客-CSDN博客
1.2.1、单文件组件命名
文件扩展名为 .vue 的 single-file components ( 单文件组件 ),
单文件组件名应该始终是 单词大写开头 ( PascalCase )
- components/
- MyComponent.vue
1.2.2、单例组件名
只拥有单个活跃实例的组件应该以 The 前缀命名,以示其 唯一性
这不意味着 组件 只可用于 一个单页面 ,而是 每个页面 只使用一次。这些组件永远不接受任何 prop ,因为它们是为你的应用 定制 的 。如果你发现有必要添加 prop ,那就表明这实际上是 一个 可复用 的 组件 ,只是 目前 在 每个页面 里只 使用一次 。
比如,头部 和 侧边栏 组件 几乎在每个页面都会使用 ,不接受 prop,该 组件 是 专门 为 该应用 所 定制 的 。
- components/
- |- TheHeading.vue
- |- TheSidebar.vue
1.2.3、基础组件名
基础组件 :不包含业务 ,独立 、具体功能 的 基础组件 ,比如 日期选择器 、模态框 等 。 这类组件作为项目的 基础控件 ,会被 大量 使用 ,因此 组件 的 API 进行过 高强度 的 抽象 ,可以通过 不同配置 实现 不同 的 功能 。
应用 特定样式 和 约定 的 基础组件 ( 也就是 展示类 的 、无逻辑 的 或 无状态 、不掺杂 业务逻辑的 组件 ) 应该 全部 以一个 特定 的 前缀 开头 —— Base 。
基础组件 在 一个页面 内可 使用多次,在 不同页面 内也可 复用,是 高可复用 组件 。
- components/
- |- BaseButton.vue
- |- BaseTable.vue
- |- BaseIcon.vue
1.2.4、业务组件
业务组件 :它不像 基础组件 只包含 某个 功能 ,而是在 业务中 被 多个页面 复用 的( 具有可复用性 ),它与 基础组件 的 区别是 ,业务组件 只在 当前项目 中会用到 ,不具有 通用性 ,而且会 包含 一些 业务 ,比如 数据请求 ;而 基础组件 不含 业务 ,在 任何项目中 都可以 使用 ,功能单一 ,比如 :一个 具有数据校验 功能 的 输入框 。
掺杂了复杂业务的组件( 拥有自身 data 、prop 的 相关处理 )即 业务组件
应该以 Custom 前缀 命名 。业务组件 在一个页面内,
比如:某个页面内有一个 卡片列表 ,而 样式 和 逻辑 跟 业务 紧密相关的卡片就是 业务组件。
- components/
- |- CustomCard.vue
1.2.5、紧密耦合的组件名
和 父组件 紧密耦合的 子组件 应该以 父组件名 作为 前缀 命名 。
因为编辑器通常会按 字母 顺序 组织文件 ,所以这样做可以把 相关联 的文件 排在一起。
- components/
- |- TodoList.vue
- |- TodoListItem.vue
- |- TodoListItemButton.vue
1.2.6、组件名中单词顺序
组件名 应该以 高级别的 ( 通常是一般化描述的 ) 单词 开头 ,以 描述性 的 修饰词 结尾 。
因为编辑器通常会按 字母顺序 组织文件,所以现在组件之间的 重要关系 一目了然 。
如下组件主要是用于 搜索 和 设置 功能 。
- components/
- |- SearchButtonClear.vue
- |- SearchButtonRun.vue
- |- SearchInputQuery.vue
- |- SearchInputExcludeGlob.vue
- |- SettingsCheckboxTerms.vue
- |- SettingsCheckboxLaunchOnStartup.vue
还有另一种 多级目录 的方式,把所有的 搜索组件 放到 “ search ” 目录 ,
把所有的 设置组件 放到 “ settings ” 目录 。
我们只推荐在非常 大型 ( 如有 100 + 个 组件 ) 的 应用下才考虑这么做 ,
因为在多级目录间找来找去 ,要比在单个 components 目录下滚动查找要花费更多的精力 。
1.2.7、完整单词的组件名
组件名 应该倾向于 完整单词 而不是 缩写 。
编辑器中的自动补全已经让 书写 长命名 的代价非常之低了,
而其带来的 明确性 却是非常宝贵的。不常用的 缩写 尤其应该 避免 。
- components/
- |- StudentDashboardSettings.vue
- |- UserProfileOptions.vue
1.3.1、name
组件名应该始终是 多个单词 ,应该始终是 PascalCase 的,
根组件 App 以及
这样做可以避免跟现有的以及未来的 HTML 元素相冲突,
因为所有的 HTML 元素名称都是单个单词的。
- export default {
- name: 'ToDoList',
- // ...
- }
1.3.2、prop
在声明 prop 的时候,其命名应该始终使用 camelCase,
而在模板和 JSX 中应该始终使用 kebab-case。
我们单纯的遵循每个语言的约定,在 JavaScript 中更自然的是 camelCase 。
而在 HTML 中则是 kebab-case。

1.3.3、router
Vue Router Path 命名采用 kebab-case 格式。
用 Snake( 如:/user_info )或
camelCase( 如:/userInfo ) 的
单词会被当成 一个 单词 ,搜索引擎 无法 区分 语义 。
- // bad
- {
- path: '/user_info', // user_info 当成一个单词
- name: 'UserInfo',
- component: UserInfo,
- meta: {
- title: ' - 用户',
- desc: ''
- }
- },
-
- // good
- {
- path: '/user-info', // 能解析成 user info
- name: 'UserInfo',
- component: UserInfo,
- meta: {
- title: ' - 用户',
- desc: ''
- }
- },
1.3.4、模板中组件
对于绝大多数项目来说,在 单文件组件 和 字符串模板 中 组件名 应该总是 PascalCase 的 ,
但是在 DOM 模板中总是 kebab-case 的。
-
- <MyComponent/>
-
-
- <my-component>my-component>
1.3.5、自闭合组件
在 单文件组件 、字符串模板 和 JSX 中 没有内容 的 组件 应该是 自闭合 的
—— 但在 DOM 模板里永远不要这样做 。
- <MyComponent/>
-
- <my-component>my-component>
1.3.6、变量
- // bad
- var getTitle = "LoginTable"
-
- // good
- let tableTitle = "LoginTable"
- let mySchool = "我的学校"
1.3.7、常量
- const MAX_COUNT = 10
- const URL = 'http://test.host.com'
1.3.8、方法
- // 1、普通情况下,使用动词 + 名词形式
- // bad
- go、nextPage、show、open、login
-
- // good
- jumpPage、openCarInfoDialog
-
- // 2、请求数据方法,以 data 结尾
- // bad
- takeData、confirmData、getList、postForm
-
- // good
- getListData、postFormData
-
- // 3、单个动词的情况
- init、refresh

1.3.9、自定义事件
自定义事件 应始终使用 kebab-case 的 事件名 。
不同于组件和 prop ,事件名 不存在 任何 自动化 的 大小写 转换 。
而是触发的 事件名 需要 完全匹配 监听这个 事件 所用的 名称 。

不同于 组件 和 prop ,事件名 不会被用作一个 JavaScript 变量名 或 property 名 ,所以 就没有 理由 使用 camelCase 或 PascalCase 了 。
并且 v-on 事件监听器 在 DOM 模板中会被 自动转换 为全 小写 ( 因为 HTML 是 大小写 不敏感 的 ) , 所以 v-on: myEvent 将会变成 v-on: myevent —— 导致 myEvent 不可能被监听到。
由原生事件可以发现其使用方式如下:
- <div
- @blur="toggleHeaderFocus"
- @focus="toggleHeaderFocus"
- @click="toggleMenu"
- @keydown.esc="handleKeydown"
- @keydown.enter="handleKeydown"
- @keydown.up.prevent="handleKeydown"
- @keydown.down.prevent="handleKeydown"
- @keydown.tab="handleKeydown"
- @keydown.delete="handleKeydown"
- @mouseenter="hasMouseHoverHead = true"
- @mouseleave="hasMouseHoverHead = false">
- div>
而为了区分 原生事件 和 自定义事件 ,在 Vue 中的使用 ,
建议除了 多单词 事件名 使用 kebab-case 的情况下 ,命名还需遵守为 on + 动词 的形式 ,
如下 :
- <div
- @on-search="handleSearch"
- @on-clear="handleClear"
- @on-clickoutside="handleClickOutside">
- div>
- // 子组件
- export default {
- methods: {
- handleTriggerItem () {
- this.$emit('on-clear')
- }
- }
- }
1.3.10、事件方法
- <div
- @click.native.stop="handleItemClick()"
- @mouseenter.native.stop="handleItemHover()">
- div>
-
- <script>
-
- export default {
- methods: {
- handleItemClick () {
- //...
- },
- handleItemHover () {
- //...
- }
- }
- }
- script>
2.1.1、代码结构
- <template>
- <div id="my-component">
- <DemoComponent />
- div>
- template>
-
- <script>
- import DemoComponent from '../components/DemoComponent'
-
- export default {
- name: 'MyComponent',
- components: {
- DemoComponent
- },
- mixins: [],
- props: {},
- data () {
- return {}
- },
- computed: {},
- watch: {}
- created () {},
- mounted () {},
- destroyed () {},
- methods: {},
- }
- script>
-
- <style lang="scss" scoped>
- #my-component {
- }
- style>
2.1.2 data
组件的 data 必须是一个函数。
- // In a .vue file
- export default {
- data () {
- return {
- foo: 'bar'
- }
- }
- }
2.1.3、prop
Prop 定义应该尽量详细。
- export default {
- props: {
- status: {
- type: String, // 规定接收的数据类型
- required: true, // 规定数据为必传项
- default: '', // 规定数据的默认值(有required时,此项可忽略)
- validator: function (value) { // 自定义验证函数
- return [
- 'syncing',
- 'synced',
- 'version-conflict',
- 'error'
- ].indexOf(value) !== -1
- }
- }
- }
- }

2.1.4、computed
应该把 复杂计算属性 分割为 尽可能多 的 更简单 的 属性 。
小的、专注的计算属性减少了信息使用时的假设性限制,所以需求变更时也用不着那么多重构了。
- // bad
- computed: {
- price: function () {
- var basePrice = this.manufactureCost / (1 - this.profitMargin)
- return (
- basePrice -
- basePrice * (this.discountPercent || 0)
- )
- }
- }
-
- // good
- computed: {
- basePrice: function () {
- return this.manufactureCost / (1 - this.profitMargin)
- },
- discount: function () {
- return this.basePrice * (this.discountPercent || 0)
- },
- finalPrice: function () {
- return this.basePrice - this.discount
- }
- }
2.1.5、为 v-for 设置键值
在组件上必须用 key 搭配 v-for,以便维护 内部组件 及其 子树 的 状态 。
甚至在元素上维护可预测的行为 ,
比如 动画中的 对象固化 (object constancy)。
- <ul>
- <li
- v-for="todo in todos"
- :key="todo.id">
- {{ todo.text }}
- li>
- ul>
2.1.6、v-if 和 v-for 互斥
永远不要把 v-if 和 v-for 同时用在同一个元素上。
- <ul>
- <li
- v-for="user in users"
- v-if="shouldShowUsers"
- :key="user.id">
- {{ user.name }}
- li>
- ul>
一般我们在两种常见的情况下会倾向于这样做:
为了过滤一个列表中的项目
( 比如
v-for="user in users" v-if="user.isActive") 。在这种情形下,请将
users替换为一个计算属性 ( 比如activeUsers) ,让其 返回 过滤后 的 列表 。
- computed: {
- activeUsers: function () {
- return this.users.filter((user) => {
- return user.isActive
- })
- }
- }
- <ul>
- <li
- v-for="user in activeUsers"
- :key="user.id">
- {{ user.name }}
- li>
- ul>
v-for="user in users" v-if="shouldShowUsers")。v-if 移动至容器元素上 ( 比如 ul, ol ) 。- <ul>
- <li
- v-for="user in users"
- v-if="shouldShowUsers"
- :key="user.id">
- {{ user.name }}
- li>
- ul>
-
- <ul v-if="shouldShowUsers">
- <li
- v-for="user in users"
- :key="user.id">
- {{ user.name }}
- li>
- ul>
2.1.7、多个 attribute 的元素
多个 attribute 的元素应该分多行撰写,每个 attribute 一行。
- <img src="https://vuejs.org/images/logo.png" alt="Vue Logo">
- <MyComponent foo="a" bar="b" baz="c"/>
- <img
- src="https://vuejs.org/images/logo.png"
- alt="Vue Logo">
-
- <MyComponent
- foo="a"
- bar="b"
- baz="c"/>
2.1.8、模板中简单的表达式
组件模板 应该只包含 简单的表达式,复杂的表达式 则应该重构为 计算属性 或 方法。
复杂表达式会让你的模板变得不那么声明式。
我们应该尽量描述应该出现的 是什么 ,而非 如何 计算那个值。
而且 计算属性 和 方法 使得代码可以 重用 。
- // bad
- {{
- fullName.split(' ').map((word) => {
- return word[0].toUpperCase() + word.slice(1)
- }).join(' ')
- }}
更好地做法 :

2.1.9、带引号的 attribute 值
非空 HTML 特性值应该始终带双引号。
- <input type=text>
- <AppSidebar :style={width:sidebarWidth+'px'}>
- <input type="text">
- <AppSidebar :style="{ width: sidebarWidth + 'px' }">
2.1.10、指令缩写
: 表示 v-bind:@ 表示 v-on:# 表示 v-slot:- <input
- :value="newTodoText"
- :placeholder="newTodoInstructions">
-
- <input
- @input="onInput"
- @focus="onFocus">
-
- <template #header>
- <h1>Here might be a page titleh1>
- template>
-
- <template #footer>
- <p>Here's some contact infop>
- template>
2.2.1、文件模板
HTML5 文件模板:
- html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <title>HTML5标准模版title>
- head>
- <body>
- body>
- html>
移动端:
- html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8" />
- <meta
- name="viewport"
- content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no"
- />
- <meta name="format-detection" content="telephone=no" />
- <title>移动端HTML模版title>
-
-
- <link rel="dns-prefetch" href="" />
-
-
-
-
-
-
-
- <link rel="stylesheet" href="css/index.css" />
-
-
- <link rel="stylesheet" href="http://srcPath/index.css" />
-
-
- head>
- <body>
-
- body>
- html>
PC 端:
- html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8" />
- <meta name="keywords" content="your keywords" />
- <meta name="description" content="your description" />
- <meta name="author" content="author,email address" />
- <meta name="robots" content="index,follow" />
- <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
- <meta name="renderer" content="ie-stand" />
- <title>PC端HTML模版title>
-
-
- <link rel="dns-prefetch" href="" />
-
-
-
-
-
-
-
- <link rel="stylesheet" href="css/index.css" />
-
-
- <link rel="stylesheet" href="http://srcPath/index.css" />
-
-
- head>
- <body>
-
- body>
- html>
2.2.2、元素及标签闭合
2.2.3、代码嵌套
2.3.1、样式文件
2.3.2、代码格式化
2.3.3、代码大小写
2.3.4、代码易读性
2.3.5、属性值引导
2.3.6、属性书写建议
2.3.7、CSS 浏览器私有前缀
2.4.1、单行代码块
2.4.2、大括号风格
2.4.3、代码中的风格
3.1.1、单行注释
3.1.2、模块注释
3.1.3、嵌套模块注释
3.2.1、单行注释
3.2.2、模块注释
3.2.3、文件注释
3.3.1、单行注释
3.3.2、多行注释
3.3.3、注释空格
3.3.4、特殊标记
3.3.5、文档类注释
3.3.6、注释工具
未完待续。。。