Vue JS 如何纠正“避免直接改变道具”?

时间:2021-02-06 09:39:41

标签: javascript vue.js

我有一个带按钮的主要组件视图:

    <mdb-btn
                      color="light-blue"
                      outline="white"
                      rounded
                      @click="showLoginRegister = true"
                      icon="users"
                      iconRight
                  >Inscription / Connexion</mdb-btn>

  export default {
  name: "Landing",
  components: {
    ...
  },
  methods: {
  },
  data() {
    return {
      showLoginRegister: false
    };
  }
};

在这个父视图中有一个子组件(一个模态窗口):

<modal-inscription :showLoginRegister="showLoginRegister"></modal-inscription>

在模态铭文组件中:

<mdb-modal :show="showLoginRegister" @close="showLoginRegister = false">...

我添加了一个道具属性:

props: ['showLoginRegister'],

当我点击按钮时它会出现模态窗口,但我在 js 控制台中有此错误消息:“[Vue 警告]:避免直接改变道具,因为每当父组件重新设置时,该值将被覆盖渲染。相反,根据道具的值使用数据或计算属性。道具正在改变:“showLoginRegister”

我理解该消息,但如何通过在子组件中使用局部变量来避免它?

也许我不使用 rignt 方法... 感谢您的帮助

2 个答案:

答案 0 :(得分:0)

正如警告消息所说 - 如果您更改 prop,它不会影响父数据,并且在父组件重新渲染后,您的 prop 将被覆盖。 为了避免这种情况,您应该从子组件 $emit 事件并在父组件中 mutate prop。

<mdb-modal :show="showLoginRegister" @close="$emit('close-login')">

    <mdb-btn
                      color="light-blue"
                      outline="white"
                      rounded
                      @click="showLoginRegister = true"
                      icon="users"
                      iconRight
                      @close-login="showLoginRegister = false"
                  >Inscription / Connexion</mdb-btn>

  export default {
  name: "Landing",
  components: {
    ...
  },
  methods: {
  },
  data() {
    return {
      showLoginRegister: false
    };
  }
};

您也可以使用 Vuex、Event Bus 或 $root/$parent 直接在组件之间进行通信。

答案 1 :(得分:0)

我不确定你的结构,但你可以获得与下面相同的结构,它应该以相同的方式工作,只需向你的父母发送一个 false 值。
只需将数据发送回父级(来自子级的 $emit)并更新父级中的给定道具!文档中有关此模式的更多信息:https://vuejs.org/v2/guide/components.html#Emitting-a-Value-With-an-Event

computed setters 也可能有所帮助,但理解起来有点复杂,因此请坚持使用基本用例。 v-model syntax on components 也是如此。


你的组件之间需要有一个 props/emit(也就是父/子)关系,比如

Parent.vue

<template>
  <div>
    <child :name="name" @update-name="updateName"></child>
  </div>
</template>

<script>
export default {
  data() {
    return {
      name: 'bob',
    }
  },
  methods: {
    updateName(newName) {
      this.name = newName
    },
  },
  components: {
    Child: () => import('./components/child'),
  },
}
</script>

Child.vue

<template>
  <div>
    <p>{{ name }}</p>
    <button @click="changeName">append nice</button>
  </div>
</template>

<script>
export default {
  props: ['name'],
  methods: {
    changeName() {
      this.$emit('update-name', this.name + ' nice')
    },
  },
}
</script>

Michael Thiessen 还就此发表了一篇博文:https://michaelnthiessen.com/avoid-mutating-prop-directly/