选择”开发者技术前线 “星标🔝,内容一触即达。点击原文更多惊喜!
开发者技术前线 汇集技术前线快讯和关注行业趋势,大厂干货,是开发者经历和成长的优秀指南。
历史推荐
点个在看,解锁更多惊喜!
点击“开发者技术前线”,选择“星标🔝”
13:21 在看|星标|留言, 真爱
https://github.com/vuejs/cn.vuejs.org/blob/master/src/v2/style-guide/index.md
App
以及 <transition>
、 <component>
之类的 Vue 内置组件除外。Vue.component('todo', {
// ...
})
export default {
name: 'Todo',
// ...
}
Vue.component('todo-item', {
// ...
})
export default {
name: 'TodoItem',
// ...
}
data
必须是一个函数。data
属性的时候 (除了 newVue
外的任何地方),它的值必须是返回一个对象的函数。data
的值是一个对象时,它会在这个组件的所有实例之间共享。想象一下,假如一个 TodoList
组件的数据是这样的:data: {
listTitle: '',
todos: []
}
data: function () {
return {
listTitle: '',
todos: []
}
}
Vue.component('some-comp', {
data: {
foo: 'bar'
}
})
export default {
data: {
foo: 'bar'
}
}
Vue.component('some-comp', {
data: function () {
return {
foo: 'bar'
}
}
})
// In a .vue file
export default {
data () {
return {
foo: 'bar'
}
}
}
// 在一个 Vue 的根实例上直接使用对象是可以的,
// 因为只存在一个这样的实例。
new Vue({
data: {
foo: 'bar'
}
})
它们写明了组件的 API,所以很容易看懂组件的用法;
在开发环境下,如果向一个组件提供格式不正确的 prop,Vue 将会告警,以帮助你捕获潜在的错误来源。
// 这样做只有开发原型系统时可以接受
props: ['status']
props: {
status: String
}
// 更好的做法!
props: {
status: {
type: String,
required: true,
validator: function (value) {
return [
'syncing',
'synced',
'version-conflict',
'error'
].indexOf(value) !== -1
}
}
}
v-if
和 v-for
用在一起 必要为了过滤一个列表中的项目 (比如 v-for="user in users"v-if="user.isActive"
)。在这种情形下,请将 users
替换为一个计算属性 (比如 activeUsers
),让其返回过滤后的列表。
为了避免渲染本应该被隐藏的列表 (比如 v-for="user in users"v-if="shouldShowUsers"
)。这种情形下,请将 v-if
移动至容器元素上 (比如 ul
, ol
)。
v-for
比 v-if
具有更高的优先级,所以这个模板:<ul>
<li
v-for="user in users"
v-if="user.isActive"
:key="user.id"
>
{{ user.name }}
</li>
</ul>
this.users.map(function (user) {
if (user.isActive) {
return user.name
}
})
computed: {
activeUsers: function () {
return this.users.filter(function (user) {
return user.isActive
})
}
}
<ul>
<li
v-for="user in activeUsers"
:key="user.id"
>
{{ user.name }}
</li>
</ul>
过滤后的列表只会在 users
数组发生相关变化时才被重新运算,过滤更高效。
使用 v-for="user in activeUsers"
之后,我们在渲染的时候只遍历活跃用户,渲染更高效。
解藕渲染层的逻辑,可维护性 (对逻辑的更改和扩展) 更强。
<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>
v-if
移动到容器元素,我们不会再对列表中的每个用户检查 shouldShowUsers
。取而代之的是,我们只检查它一次,且不会在 shouldShowUsers
为否的时候运算 v-for
。<ul>
<li
v-for="user in users"
v-if="user.isActive"
:key="user.id"
>
{{ user.name }}
</li>
</ul>
<ul>
<li
v-for="user in users"
v-if="shouldShowUsers"
:key="user.id"
>
{{ user.name }}
</li>
</ul>
<ul>
<li
v-for="user in activeUsers"
:key="user.id"
>
{{ user.name }}
</li>
</ul>
<ul v-if="shouldShowUsers">
<li
v-for="user in users"
:key="user.id"
>
{{ user.name }}
</li>
</ul>
Vue.component('TodoList', {
// ...
})
Vue.component('TodoItem', {
// ...
})
components/
|- TodoList.js
|- TodoItem.js
components/
|- TodoList.vue
|- TodoItem.vue
components/
|- ClearSearchButton.vue
|- ExcludeFromSearchInput.vue
|- LaunchOnStartupCheckbox.vue
|- RunSearchButton.vue
|- SearchInput.vue
|- TermsCheckbox.vue
components/
|- SearchButtonClear.vue
|- SearchButtonRun.vue
|- SearchInputExcludeGlob.vue
|- SearchInputQuery.vue
|- SettingsCheckboxLaunchOnStartup.vue
|- SettingsCheckboxTerms.vue
在多级目录间找来找去,要比在单个 components
目录下滚动查找要花费更多的精力。
存在组件重名 (比如存在多个 ButtonDelete
组件) 的时候在编辑器里更难快速定位。
让重构变得更难,因为为一个移动了的组件更新相关引用时,查找/替换通常并不高效。
components/
|- ClearSearchButton.vue
|- ExcludeFromSearchInput.vue
|- LaunchOnStartupCheckbox.vue
|- RunSearchButton.vue
|- SearchInput.vue
|- TermsCheckbox.vue
components/
|- SearchButtonClear.vue
|- SearchButtonRun.vue
|- SearchInputQuery.vue
|- SearchInputExcludeGlob.vue
|- SettingsCheckboxTerms.vue
|- SettingsCheckboxLaunchOnStartup.vue
components/
|- SdSettings.vue
|- UProfOpts.vue
components/
|- StudentDashboardSettings.vue
|- UserProfileOptions.vue
props: {
'greeting-text': String
}
props: {
greetingText: String
}
<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"
/>
易于测试
当每个计算属性都包含一个非常简单且很少依赖的表达式时,撰写测试以确保其正确工作就会更加容易。
易于阅读
简化计算属性要求你为每一个值都起一个描述性的名称,即便它不可复用。这使得其他开发者 (以及未来的你) 更容易专注在他们关心的代码上并搞清楚发生了什么。
更好的“拥抱变化”
任何能够命名的值都可能用在视图上。举个例子,我们可能打算展示一个信息,告诉用户他们存了多少钱;也可能打算计算税费,但是可能会分开展现,而不是作为总价的一部分。
小的、专注的计算属性减少了信息使用时的假设性限制,所以需求变更时也用不着那么多重构了。
computed: {
price: function () {
var basePrice = this.manufactureCost / (1 - this.profitMargin)
return (
basePrice -
basePrice * (this.discountPercent || 0)
)
}
}
computed: {
basePrice: function () {
return this.manufactureCost / (1 - this.profitMargin)
},
discount: function () {
return this.basePrice * (this.discountPercent || 0)
},
finalPrice: function () {
return this.basePrice - this.discount
}
}
v-if
/ v-else-if
/ v-else
中使用 key
谨慎使用v-if
+ v-else
的元素类型相同,最好使用 key
(比如两个 <div>
元素)。<div v-if="error">
错误:{{ error }}
</div>
<div v-else>
{{ results }}
</div>
<div
v-if="error"
key="search-status"
>
错误:{{ error }}
</div>
<div
v-else
key="search-results"
>
{{ results }}
</div>
scoped
中的元素选择器 谨慎使用scoped
中出现。scoped
样式中,类选择器比元素选择器更好,因为大量使用元素选择器是很慢的。data-v-f3f3eg9
。然后修改选择器,使得在匹配选择器的元素中,只有带这个特性才会真正生效 (比如 button[data-v-f3f3eg9]
)。button[data-v-f3f3eg9]
) 会比类和特性组合的选择器慢,所以应该尽可能选用类选择器。<template>
<button>X</button>
</template>
<style scoped>
button {
background-color: red;
}
</style>
<template>
<button class="btn btn-close">X</button>
</template>
<style scoped>
.btn-close {
background-color: red;
}
</style>
this.$parent
或改变 prop。this.$parent
能够简化两个深度耦合的组件。Vue.component('TodoItem', {
props: {
todo: {
type: Object,
required: true
}
},
template: '<input v-model="todo.text">'
})
Vue.component('TodoItem', {
props: {
todo: {
type: Object,
required: true
}
},
methods: {
removeTodo () {
var vm = this
vm.$parent.todos = vm.$parent.todos.filter(function (todo) {
return todo.id !== vm.todo.id
})
}
},
template: `
<span>
{{ todo.text }}
<button @click="removeTodo">
X
</button>
</span>
`
})
Vue.component('TodoItem', {
props: {
todo: {
type: Object,
required: true
}
},
template: `
<input
:value="todo.text"
@input="$emit('input', $event.target.value)"
>
`
})
Vue.component('TodoItem', {
props: {
todo: {
type: Object,
required: true
}
},
template: `
<span>
{{ todo.text }}
<button @click="$emit('delete')">
X
</button>
</span>
`
})
this.$root
或一个全局事件总线。this.$root
和/或全局事件总线管理状态在很多简单的情况下都是很方便的,但是并不适用于绝大多数的应用。Vuex 提供的不仅是一个管理状态的中心区域,还是组织、追踪和调试状态变更的好工具。// main.js
new Vue({
data: {
todos: []
},
created: function () {
this.$on('remove-todo', this.removeTodo)
},
methods: {
removeTodo: function (todo) {
var todoIdToRemove = todo.id
this.todos = this.todos.filter(function (todo) {
return todo.id !== todoIdToRemove
})
}
}
})
// store/modules/todos.js
export default {
state: {
list: []
},
mutations: {
REMOVE_TODO (state, todoId) {
state.list = state.list.filter(todo => todo.id !== todoId)
}
},
actions: {
removeTodo ({ commit, state }, todo) {
commit('REMOVE_TODO', todo.id)
}
}
}
<!-- TodoItem.vue -->
<template>
<span>
{{ todo.text }}
<button @click="removeTodo(todo)">
X
</button>
</span>
</template>
<script>
import { mapActions } from 'vuex'
export default {
props: {
todo: {
type: Object,
required: true
}
},
methods: mapActions(['removeTodo'])
}
</script>
---END---
选择”开发者技术前线 “星标🔝,内容一触即达。点击原文更多惊喜!
开发者技术前线 汇集技术前线快讯和关注行业趋势,大厂干货,是开发者经历和成长的优秀指南。
历史推荐
点个在看,解锁更多惊喜!