组件/实例选项顺序
组件/实例选项的顺序应该一致
这是我们推荐的组件选项的默认顺序。他们被分成不同的分类,所以你会知道在插件的哪里添加新的属性。
- 副作用(组件之外触发)
el
- 全局意识(要求组件之外的知识)
name
parent
- 组件类型(改变组件的类型)
functional
- 组件修饰符(改变组件被编译的方式)
delimiters
comments
- 组件依赖(资源在模板内使用)
components
directive
filters
- Composition(将属性合并到选项内)
extends
mixins
- Interface(组件界面)
inheritAttrs
model
props/propsData
- 本地状态(本地响应属性)
data
computed
- Event(响应事件触发回调)
watch
- 事件循环(按它们被调用的顺序)
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
activated
deactivated
beforeDestory
destroyed
- 非响应式属性(独立于响应式系统的实例属性)
methods
- 渲染(组件输出的声明性描述)
template/render
renderError
元素特性顺序
元素的特性(包括组件)的顺序应该一致。
以下是我们推荐的组件选项的默认顺序。他们被分为不同的分类,所以你会知道在哪个添加自定义的特性和指令。
- 定义(提供组件选项)
is
- 列表渲染(创建相同元素的多个变体)
v-for
- 条件(元素被怎样渲染/展示)
v-if
v-else-if
v-else
v-show
v-cloak
- 渲染修饰符(改变元素渲染的方式)
v-pre
v-once
- 全局意识(要求组件以外的知识)
id
- 唯一特性(需要唯一值的特性)
ref
key
slot
- 双向绑定(结合绑定和事件)
v-model
- 其他特性(所有未指定的绑定 & 未绑定的特性)
- Events(组件事件监听)
v-on
- 内容(复写元素的内容)
v-html
v-text
在组件/实例选项内空行
你可能想在多行属性之间添加空行,特别是如果这些选项在非滚动的屏幕不合适时。
当组件感觉狭小或阅读困难,在多行属性之间添加空格可以使他们更容易浏览。在一些编辑器,例如Vim,这样的格式化选项也可以使他们更容易在键盘上导航。
Good1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24props: {
value: {
type: String,
required: true
},
focused: {
type: Boolean,
default: false
},
label: String,
icon: String
},
computed: {
formattedValue: function () {
// ...
},
inputClasses: function () {
// ...
}
}
1 | // 没有空格也可以只要是组件 |
单文件组件最外层元素的顺序
单文件组件应该总是<script>
,<template>
,和<style>
标签顺序,<style>
在最后,因为另外两个标签至少要有一个。
Bad1
2
3
4// In HTML
<style>/* ... */</style>
<script>/* ... */</script>
<template>...</template>
1 | // In HTML |
Good1
2
3
4
5
6
7
8
9
10// In HTML
<!-- ComponentA.vue -->
<script>/* ... */</script>
<template>...</template>
<style>/* ... */</style>
<!-- ComponentB.vue -->
<script>/* ... */</script>
<template>...</template>
<style>/* ... */</style>
1 | <!-- ComponentA.vue --> |
优先级D规则:谨慎使用(有潜在危险的模式)
v-if
/v-else-if
/v-else
没有key
最好使用携带key
的v-if
+ v-else
,如果他们是相同而元素类型(e.g.都是<div>
元素)。
默认情况下,Vue尽可能高效的更新DOM,那意味着当切换两个相同元素的时候,它仅仅分发已经存在的元素,而不出删除它再去添加一个新的。如果这些元素实际上不应该被认为是同一个可能产生意外的后果。
Bad1
2
3
4
5
6<div v-if="error">
Error: {{ error }}
</div>
<div v-else>
{{ results }}
</div>
Good1
2
3
4
5
6
7
8
9
10
11
12<div
v-if="error"
key="seach-status"
>
Error: {{ error }}
</div>
<div
v-else
key="search-results"
>
{{ results }}
</div>
1 | <p v-if="error"> |
使用scoped
的元素选择器
元素选择器应该避免在scoped
中出现。
在scoped
样式中,应该首选类选择器而不是元素选择器,因为大量使用元素选择器是很慢的。
详细解释
对于scoped样式,Vue为组件元素添加了唯一特性,例如:data-v-f3f3eg9
。然后修改选择器,以便匹配这些与此元素匹配的元素(例如:button[data-v-f3f3eg9]
).问题是大量的元素特性选择器(例如:
button[data-v-f3f3eg9]
)将会相当慢比类特性选择器,所以无论何时类选择器是首选。
Bad1
2
3
4
5
6
7
8
9<template>
<button>X</button>
</template>
<style scoped>
button {
background-color: red;
}
</style>
Good1
2
3
4
5
6
7
8
9<template>
<button class="btn btn-close">X</button>
</template>
<style scoped>
.btn-close {
background-color: red
}
</style>
隐式的父-子组件通信
Props和事件应该作为父-子间通信的首选,代替this.$parent
或改变props。
一个理想的Vue应用是props向下传递,事件向上传递。坚持这个惯例使你的组件更容易理解。然而,在一些边缘情况下prop的变更或this.$parent
能够简化两个已经深度耦合的组件。
问题是,在许多简单的场景下这种模式可能提供便利。但请当心:不要为了短期的方便(少写代码)而以能够理解的状态流作为交换。
bad1
2
3
4
5
6
7
8
9
10// In JS
Vue.component('TodoItem',{
props: {
todo: {
type: Object,
required: true
}
},
template: '<input v-model="todo.text">'
})
1 | Vue.component('TodoItem',{ |
Good1
2
3
4
5
6
7
8
9
10
11
12Vue.component('TodoItem', {
props: {
todo: {
type: Object,
required: true
}
},
template: `
<input
:value="todo.text"
@input="$emit('input', $event.target.value)"
})
1 | Vue.component('TodoItem',{ |
非Flux状态管理
Vuex是全局状态管理的首选,代替this.$root
或一个全局事件总线。
使用this.$root
和/或使用全局事件总线管理状态是一种惯例对于非常简单的场景,但是对大多数应用不合适。Vuex不仅提供了一个中心区域去管理状态,而且也是组织、追踪和调试状态改变的工具。
Bad1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// main.js
new Vue({
data: {
todos:[]
},
created: function () {
this.$on('remove-todo',this.removeTodo)
},
methods:{
removeTodo: function (todo) {
var todoIdToRemove = tood.id
this.todos = this.todos.filter(function (todo) {
return todo.id !== todoToRemove
})
}
}
})
Good1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// store/modules/todos.js
export default {
state: {
list: []
},
mutations: {
REMOVE_TODO(state,todoId) {
state.list = state.list.filter(todo => todo.id !== toodId)
}
},
actions: {
removeTodo ({ commit, state }, todo) {
commit('REMOVE_TODD',todo.id)
}
}
}
1 | // In HTML |