避免直接道具突变会增加变量的重新声明

时间:2018-08-31 15:40:48

标签: javascript vue.js

我有一个对话框组件:

<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属性? 如果父母有xyz个数据道具,那么如果我想在孩子身上进行突变,孩子也应该声明他们?我们不是在重复自己吗?如何防止这种重复?

1 个答案:

答案 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>