vue-standard

Vue 前端开发规范

以下规范均可参考 VUE 官方的 风格指南

组件名

所有的Component文件都是以大写开头 (PascalCase),这也是官方所推荐的

但除了 index.vue

例子:

1
2
3
@/components/BackToTop/index.vue
@/components/Charts/Line.vue
@/views/example/components/Button.vue

组件名为多个单词,并且用连接线(-)连接,避免与 HTML 标签冲突,并且结构更加清晰

1
2
3
4
5
6
7
8
9
// 反例
export default {
name: 'item'
}

// 正例
export default {
name: 'page-article-item'
}

组件页面

views文件下,代表路由的.vue文件都使用横线连接 (kebab-case),代表路由的文件夹也是使用同样的规则。

例子:

  • @/views/svg-icons/index.vue
  • @/views/svg-icons/require-icons.js

使用横线连接 (kebab-case)来命名views主要是出于以下几个考虑。

  • 横线连接 (kebab-case) 也是官方推荐的命名规范之一 文档
  • views下的.vue文件代表的是一个路由,所以它需要和component进行区分(component 都是大写开头)
  • 页面的url 也都是横线连接的,比如https://www.xxx.admin/export-excel,所以路由对应的view应该要保持统一
  • 没有大小写敏感问题

编写页面的时候尽量组件化。

比如:在全局的 @/components 只会写一些全局的组件,如富文本,各种搜索组件,封装的日期组件等等能被公用的组件。每个页面或者模块特定的业务组件则会写在当前 views 下面。如:@/views/article/components/xxx.vue。这样拆分大大减轻了维护成本。

请记住拆分组件最大的好处不是公用而是可维护性!

Prop

定义 Prop 的时候应该始终以驼峰格式(camelCase)命名,在父组件赋值的时候使用连接线(-)。这里遵循每个语言的特性,因为在 HTML 标记中对大小写是不敏感的,使用连接线更加友好;而在 JavaScript 中更自然的是驼峰命名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 正例:Prop 的定义应该尽量详细的指定其类型、默认值和验证
props: {
articleStatus: {
type: Boolean,
required: true,
default () {
return false
}
}
}
// 反例
props: ['articleStatus']

// HTML
<article-item :article-status="true"></article-item>

v-for

v-for 应该避免与 v-if 在同一个元素(例如:< li >)上使用,因为 v-for 的优先级比 v-if 更高,为了避免无效计算和渲染,应该尽量将 v-if 放到容器的父元素之上。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 反例
<ul>
<li v-for="item in list" :key="item.id" v-if="showList">
{{ item.title }}
</li>
</ul>

// 正例
<ul v-if="showList">
<li v-for="item in list" :key="item.id">
{{ item.title }}
</li>
</ul>

v-if / v-else-if / v-else

若同一组 v-if 逻辑控制中的元素逻辑相同,Vue 为了更高效的元素切换,会复用相同的部分,例如:value。为了避免复用带来的不合理效果,应该在同种元素上加上 key 做标识。

示例:

1
2
3
4
5
6
7
// 正例
<div v-if="hasData" key="mazey-data">
<span>{{ mazeyData }}</span>
</div>
<div v-else key="mazey-none">
<span>无数据</span>
</div>

样式

页面的样式和组件是一个道理,全局的 @/style 放置一下全局公用的样式,每一个页面的样式就写在当前 views下面

为了避免样式冲突,整个项目要么全都使用 scoped 特性,要么使用 BEM 约定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 正例
<!-- 使用 scoped 特性 -->
<template>
<button class="btn btn-sure">确认</button>
</template>
<style scoped>
.btn{
border: 1px solid #F1F1F1;
}
.btn-sure{
background-color: blue;
}
</style>

<!-- 使用 BEM(Block Element Modifier) 特性 -->
<template>
<button class="menu-btn menu-btn-sure">确认</button>
</template>
<style>
.menu-btn{
border: 1px solid #F1F1F1;
}
.menu-btn-sure{
background-color: blue;
}
</style>

JavaScript

  • 所有的.js文件都遵循横线连接 (kebab-case)。
1
2
3
@/utils/open-window.js
@/views/svg-icons/require-icons.js
@/components/MarkdownEditor/default-options.js
  • 建议不再使用 var,而使用 let / const,如果变量不会被修改则使用 const,否则使用 let
  • 不再使用双引号,静态字符串使用单引号
1
2
3
// 正例
const foo = '后除'
const bar = `${foo},前端工程师`
  • 匿名函数统一使用箭头函数,多个参数/返回值时优先使用对象的解构赋值
1
2
3
4
5
// 正例
function getPersonInfo ({name, sex}) {
// ...
return {name, gender}
}

对象扩展属性

建议使用扩展运算符拷贝对象而不是 Object.assign(target, ...sources)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 错误
const foo = {a: 0, b: 1}
const bar = Object.assign(foo, {c: 2})

// 反例
const foo = {a: 0, b: 1}
const bar = Object.assign({}, foo)

// 正例
const foo = {a: 0, b: 1}
const bar = JSON.parse(JSON.stringify(foo))

// 极好
const foo = {a: 0, b: 1}
const bar = {...foo, c: 2}

关于 Eval

避免使用 eval,如要进行字符串转化为对象,最好使用浏览器的内置方法来解析 JSON 数据,以确保代码的安全性和数据的合法性。如果浏览器不支持 JSON.parse(),你可以使用 JSON.org 所提供的库。如果不得不使用 eval(),可以尝试用 new Function() 来代替,在 new Function() 中运行的代码会在一个局部函数作用域内执行,因此源码中定义的变量不会自动变成全局变量。

发布于

2017-08-22

更新于

2022-01-11

许可协议

# 推荐文章
  1.PostgreSQL
  2.elasticsearch
  3.防火墙
  4.git
  5.https证书
  6.jenkins

:D 一言句子获取中...