本规范提供了一种统一的编码规范来编写 Vue.js 代码。这使得代码具有如下的特性:
本指南为 De Voorhoede 参考 RiotJS 编码规范 而写。
this
赋值给 component
变量始终基于模块的方式来构建你的 app,每一个子模块只做一件事情。
Vue.js 的设计初衷就是帮助开发者更好的开发界面模块。一个模块是应用程序中独立的一个部分。
每一个 Vue 组件(等同于模块)首先必须专注于解决一个 单一的问题 , 独立的 , 可复用的 , 微小的 and 可测试的 。
如果你的组件做了太多的事或是变得臃肿,请将其拆分成更小的组件并保持单一的原则。一般来说,尽量保证每一个文件的代码行数不要超过 100 行。也请保证组件可独立的运行。比较好的做法是增加一个单独的 demo 示例。
组件的命名需遵从以下原则:
同时还需要注意:
app-
前缀作为命名空间 : 如果非常通用的话可使用一个单词来命名,这样可以方便于其它项目里复用。
<app-header>app-header>
<user-list>user-list>
<range-slider>range-slider>
<btn-group>btn-group>
<ui-slider>ui-slider>
<slider>slider>
Vue.js 的表达式是 100% 的 Javascript 表达式。这使得其功能性很强大,但也带来潜在的复杂性。因此,你应该尽量 保持表达式的简单化 。
如果你发现写了太多复杂并难以阅读的行内表达式,那么可以使用 method 或是 computed 属性来替代其功能。
<template>
<h1>
{{ `${year}-${month}` }}
h1>
template>
<script type="text/Javascript">
export default {
computed: {
month() {
return this.twoDigits((new Date()).getUTCMonth() + 1);
},
year() {
return (new Date()).getUTCFullYear();
}
},
methods: {
twoDigits(num) {
return ('0' + num).slice(-2);
}
},
};
script>
<template>
<h1>
{{ `${(new Date()).getUTCFullYear()}-${('0' + ((new Date()).getUTCMonth()+1)).slice(-2)}` }}
h1>
template>
虽然 Vue.js 支持传递复杂的 Javascript 对象通过 props 属性,但是你应该尽可能的使用原始类型的数据。尽量只使用 Javascript 原始类型 (字符串、数字、布尔值) 和 函数。尽量避免复杂的对象。
组件的每一个属性单独使用一个 props,并且使用函数或是原始类型的值。
<range-slider
:values="[10, 20]"
min="0"
max="100"
step="5"
:on-slide="updateInputs"
:on-end="updateResults">
range-slider>
<range-slider :cOnfig="complexConfigObject">range-slider>
在 Vue.js 中,组件的 props 即 API,一个稳定并可预测的 API 会使得你的组件更容易被其他开发者使用。
组件 props 通过自定义标签的属性来传递。属性的值可以是 Vue.js 字符串( :attr="value"
或v-bind:attr="value"
)或是不传。你需要保证组件的 props 能应对不同的情况。
验证组件 props 可以保证你的组件永远是可用的(防御性编程)。即使其他开发者并未按照你预想的方法使用时也不会出错。
type
属性 校验类型<template>
<input type="range" v-model="value" :max="max" :min="min">
template>
<script type="text/Javascript">
export default {
props: {
max: {
type: Number, // 这里添加了数字类型的校验
default() { return 10; },
},
min: {
type: Number,
default() { return 0; },
},
value: {
type: Number,
default() { return 4; },
},
},
};
script>
this
赋值给 component
变量(在 Vue.js 组件上下文中, this
指向了组件实例。因此当你切换到了不同的上下文时,要确保this
指向一个可用的 component
变量。
换句话说,不要在编写这样的代码 const self = this;
,而是应该直接使用变量 component
。
this
赋值给变量 component
可用让开发者清楚的知道任何一个被使用的地方,它代表的是组件实例。<script type="text/Javascript">
export default {
methods: {
hello() {
return 'hello';
},
printHello() {
console.log(this.hello());
},
},
};
script>
<script type="text/Javascript">
export default {
methods: {
hello() {
return 'hello';
},
printHello() {
const self = this; // 没有必要
console.log(self.hello());
},
},
};
script>
按照一定的结构组织,使得组件便于理解。
name
属性。借助于 vue devtools 可以让你更方便的测试组件结构化
<template lang="html">
<div class="Ranger__Wrapper">
div>
template>
<script type="text/Javascript">
export default {
// 不要忘记了 name 属性
name: 'RangeSlider',
// 组合其它组件
extends: {},
// 组件属性、变量
props: {
bar: {}, // 按字母顺序
foo: {},
fooBar: {},
},
// 变量
data() {},
computed: {},
// 使用其它组件
components: {},
// 方法
watch: {},
methods: {},
// 生命周期函数
beforeCreate() {},
mounted() {},
};
script>
<style scoped>
.Ranger__Wrapper { /* ... */ }
style>
Vue.js 提供的处理函数和表达式都是绑定在 ViewModel 上的,组件的每一个事件都应该按照一个好的命名规范来,这样可以避免不少的开发问题,具体可见如下 ** 为什么**。
Vue.js 支持组件嵌套,并且子组件可访问父组件的上下文。访问组件之外的上下文违反了 基于模块开发 的 第一原则 。因此你应该尽量避免使用 this.$parent
。
Vue.js 支持通过 ref
属性来访问其它组件和 HTML 元素。并通过 this.$refs
可以得到组件或 HTML 元素的上下文。在大多数情况下,通过 this.$refs
来访问其它组件的上下文是可以避免的。在使用的的时候你需要注意避免调用了不恰当的组件 API,所以应该尽量避免使用 this.$refs
。
this.$refs
来实现。this..$ref
而不是 JQuery
, document.getElement*
, document.queryElement
。
<range :max="max"
:min="min"
@current-value="currentValue"
:step="1">range>
<modal ref="basicModal">
<h4>Basic Modalh4>
<button class="primary" @click="$refs.basicModal.close()">Closebutton>
modal>
<button @click="$refs.basicModal.open()">Open modalbutton>
<template>
<div v-show="active">
div>
template>
<script>
export default {
// ...
data() {
return {
active: false,
};
},
methods: {
open() {
this.active = true;
},
hide() {
this.active = false;
},
},
// ...
};
script>
<template>
<range :max="max"
:min="min"
ref="range"
:step="1">range>
template>
<script>
export default {
// ...
methods: {
getRangeCurrentValue() {
return this.$refs.range.currentValue;
},
},
// ...
};
script>
Vue.js 的组件是自定义元素,这非常适合用来作为样式的根作用域空间。可以将组件名作为 css 类的命名空间。
使用组件名作为样式命名的前缀,可基于 BEM 或 OOCSS 范式。同时给style标签加上 scoped 属性。加上 scoped 属性编译后会给组件的 class 自动加上唯一的前缀从而避免样式的冲突。
<style scoped>
/* 推荐 */
.MyExample { }
.MyExample li { }
.MyExample__item { }
/* 避免 */
.My-Example { } /* not scoped to component or module name, not BEM compliant */
style>
使用 Vue.js 组件的过程中会创建 Vue 组件实例,这个实例是通过自定义属性配置的。为了便于其他开发者使用该组件,对于这些自定义属性即组件API应该在 README.md
文件中进行说明。
README.md
是标准的我们应该首先阅读的文档文件。代码托管网站 (github/bitbucket/gitlab 等) 会默认在仓库中展示 该文件作为仓库的介绍。在模块目录中添加 README.md
文件:
range-slider/
├── range-slider.vue
├── range-slider.less
└── README.md
在 README 文件中说明模块的功能以及使用场景。对于 vue 组件来说,比较有用的描述是组件的自定义属性即 API 的描述介绍。
range slider 组件可通过拖动的方式来设置一个给定范围内的数值。
该模块使用 noUiSlider 来实现夸浏览器和 touch 功能的支持。
支持如下的自定义属性:
attribute | type | description |
---|---|---|
min |
Number | 可拖动的最小值. |
max |
Number | 可拖动的最大值. |
values |
Number[] optional | 包含最大值和最小值的数组. 如. values="[10, 20]" . Defaults to [opts.min, opts.max] . |
step |
Number optional | 增加减小的数值单位,默认为 1. |
on-slide |
Function optional | 用户拖动开始按钮或者结束按钮时的回调函数,函数接受 (values, HANDLE) 格式的参数。 如: on-slide={ updateInputs } , component.updateInputs = (values, HANDLE) => { const value = values[HANDLE]; } . |
on-end |
Function optional | 当用户停止拖动时触发的回调函数,函数接受 (values, HANDLE) 格式的参数。 |
如需要自定义 slider 的样式可参考 noUiSlider 文档
添加 index.html
文件作为组件的 demo 示例,并提供不同配置情况的效果,说明组件是如何使用的。
代码校验可以保持代码的统一性以及追踪语法错误。.vue 文件可以通过使用 eslint-plugin-html
插件来校验代码。你可以通过 vue-cli
来开始你的项目, vue-cli
默认会开启代码校验功能。
为了校验工具能够校验 *.vue
文件,你需要将代码编写在 标签中,并使,因为校验工具无法理解行内表达式,配置校验工具可以访问全局变量
vue
和组件的 props
。
ESLint 需要通过 ESLint HTML 插件 来抽取组件中的代码。
通过 .eslintrc
文件来配置 ESlint,这样 IED 可以更好的理解校验配置项。 ESlint,这样.
{
"extends": "eslint:recommended",
"plugins": ["html"],
"env": {
"browser": true
},
"globals": {
"opts": true,
"vue": true
}
}
运行 ESLint
eslint src/**/*.vue
JSHint 可以解析 HTML (使用 --extra-ext
命令参数) 和 抽取代码(使用 --extract=auto
命令参数).
通过 .jshintrc
文件来配置 ESlint,这样 IED 可以更好的理解校验配置项。
{
"browser": true,
"predef": ["opts", "vue"]
}
运行 JSHint
jshint --config modules/.jshintrc --extra-ext=html --extract=auto modules/
注:JSHint 不接受 vue
扩展名的文件,只支持 html
。
本人demo地址:
https://github.com/HerbertKarajan/H5Platform
https://github.com/HerbertKarajan/Vue-smallGame