我有一个对话框组件:
<div v-if="dialog">
<p>Worlds smallest dialog</p>
<button @click="dialog = false>Close Dialog</button> // Avoid mutating props directly...
</div>
//Instance options:
props: {
dialog: {
type: Boolean,
default: false
}
}
如果我想在父组件中使用它:
<button @click="dialog = true">Open Dialog</button>
<dialog :dialog="dialog"></dialog>
// Data object:
data: {
dialog: false,
}
这有效,我的意思是应用程序没有损坏。但是我被警告说,我应该声明一个数据/计算属性;这很奇怪,因为如果我想突变5-7个道具,那么对于每个道具我也必须在子组件上声明一个data属性?
如果父母有x
,y
,z
个数据道具,那么如果我想在孩子身上进行突变,孩子也应该声明他们?我们不是在重复自己吗?如何防止这种重复?
答案 0 :(得分:3)
父母和孩子都应具有独立声明的数据/属性。这个想法是您要分离每个组件的关注点。只有组件知道其实际需要。如果您删除属性或将属性添加到子项或父项,则这两种实现都会更改,因为它们直接由数据/属性耦合。通过同时声明两个元素,更改一个元素不会立即破坏两个组件的API。
此外,出于某些原因,直接注入到组件中的变异道具被视为反模式。从文档Prop Mutation中考虑这一点:
在本地更改道具现在被认为是一种反模式,例如 声明道具,然后将
this.myProp = 'someOtherValue'
设置为 组件。由于采用了新的渲染机制,无论何时父级 重新渲染组件,子组件的本地更改将是 覆盖。
Vue的口头禅之一是“道具降下,事件增高”。事件不关心父母的实现,无论父母是否在听,事件都会触发。再次简化了父级数据更改的情况,因为您再次不必更改子级的道具即可防止API损坏。
在您的示例中,不应直接设置具有<button>
的子对话框。它应将事件传播到父组件,并告诉父组件“单击了关闭按钮,请考虑一下。”然后,父母应该决定是否将dialog
道具设置为false
。
在此示例中,对话框组件发出“关闭”事件,根本不需要使用道具:
Vue.component('my-dialog', {
template: `
<div>
<p>Worlds smallest dialog</p>
<button @click="$emit('close')">
Close Dialog
</button>
</div>
`
})
new Vue({
el: '#app',
data() {
return { dialog: false }
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app">
<button @click="dialog = true">Show Dialog</button>
<my-dialog v-show="dialog" @close="dialog = false">
</my-dialog>
</div>