Vue 模式是props 向下和events 向上。这听起来很简单,但在编写自定义组件时很容易忘记。
从 Vue 2.2.0 开始,您可以使用 v-model(和 computed properties)。我发现这种组合在组件之间创建了一个简单、干净且一致的接口:
- 传递给您的组件的任何
props 都保持反应状态(即,它不会被克隆,也不需要watch 函数在检测到更改时更新本地副本)。
- 更改会自动发送给父级。
- 可与多个级别的组件一起使用。
计算属性允许单独定义 setter 和 getter。这允许Task 组件被重写如下:
Vue.component('Task', {
template: '#task-template',
props: ['list'],
model: {
prop: 'list',
event: 'listchange'
},
computed: {
listLocal: {
get: function() {
return this.list
},
set: function(value) {
this.$emit('listchange', value)
}
}
}
})
model 属性定义了哪个prop 与v-model 相关联,以及哪个事件将在更改时发出。然后,您可以从父级调用此组件,如下所示:
<Task v-model="parentList"></Task>
listLocal 计算属性在组件内提供了一个简单的 getter 和 setter 接口(将其视为私有变量)。在#task-template 中,您可以渲染listLocal,并且它将保持反应状态(即,如果parentList 更改,它将更新Task 组件)。您还可以通过调用 setter(例如,this.listLocal = newList)来改变 listLocal,它会将更改发送给父级。
这种模式的优点在于您可以将listLocal 传递给Task 的子组件(使用v-model),子组件的更改将传播到顶级组件。
例如,假设我们有一个单独的EditTask 组件,用于对任务数据进行某种类型的修改。通过使用相同的v-model 和计算属性模式,我们可以将listLocal 传递给组件(使用v-model):
<script type="text/x-template" id="task-template">
<div>
<EditTask v-model="listLocal"></EditTask>
</div>
</script>
如果EditTask 发出更改,它将适当地在listLocal 上调用set(),从而将事件传播到顶层。同样,EditTask 组件也可以使用v-model 调用其他子组件(如表单元素)。