避免改变道具:vuejs 2

问题描述 投票:2回答:2

这是我运行代码时控制台中出现的内容:“避免直接改变道具,因为只要父组件重新渲染,该值就会被覆盖。而是根据道具的值使用数据或计算属性。支持变异: “器isChecked””。我已经看到其他帖子对此有何评论,但我不能适应我的问题。有人可以向我解释一下吗?

父母:模板:

<div class="checkBox-container">
<input type="checkbox"/>
<!-- <div class="check" :class="[size]" v-if="!isChecked"></div>
<div class="check" :class="[size]" v-else>
  <div>v</div>
</div> -->
<div class="check" :class="[size]" @click="changeVal">
  <div v-if="isChecked">v</div>
</div>
<div><label class="label">{{label}}</label></div>
<div><span class="subLabel">{{subLabel}}</span></div>

脚本:

export default {
  name: "ax-checkbox",
  props: {
     label: String,
    subLabel: String,
    size: String,
    isChecked: false,
    checks: []
  },
  methods: {
    changeVal() {
      this.isChecked = !this.isChecked;
      this.$emit("changeVal");
    }
  }
};

儿童

<div class="filters">
    <ax-checkbox label="Où :" subLabel="Ville" size="small"></ax-checkbox>
    <div class="separator"></div>
    <ax-checkbox label="Quoi :" subLabel="Thématique(s)" size="small"></ax-checkbox>
    <div class="separator"></div>
    <ax-checkbox label="Quand :" subLabel="Dans..." size="small"></ax-checkbox>
</div>
vue.js vuejs2
2个回答
0
投票

由于您似乎正在尝试更新传递到组件中的属性的值,因此您的组件实际上是一个自定义输入组件。看看excellent Vue docs on this topic。我总结了下面的想法。

Vue中的双向数据绑定由v-model处理。应用于您的isChecked属性,这归结为v-model="isChecked",实际上是:value="isChecked" @input="evt => isChecked = evt.target.value"的语法糖。

因此,对于您的组件,您需要执行以下操作:

  1. isChecked属性的名称更新为value
  2. 在你的changeVal方法中,发出一个输入事件,如: changeVal() { this.$emit("input", !this.value); }

如果需要,你仍然可以发出changeVal事件。


3
投票

你变异的道具是isChecked

因此,创建一个本地数据变量(用isChecked初始化它)并改为变异:

export default {
  name: "ax-checkbox",
  props: {
     label: String,
    subLabel: String,
    size: String,
    isChecked: false,
    checks: []
  },
  data() {
    return {isCheckedInternal: this.isChecked}
  },
  methods: {
    changeVal() {
      this.isCheckedInternal = !this.isCheckedInternal;
      this.$emit("changeVal");
    }
  }
};

并在模板中替换它:

<div class="checkBox-container">
<input type="checkbox"/>
<!-- <div class="check" :class="[size]" v-if="!isCheckedInternal"></div>
<div class="check" :class="[size]" v-else>
  <div>v</div>
</div> -->
<div class="check" :class="[size]" @click="changeVal">
  <div v-if="isCheckedInternal">v</div>
</div>
<div><label class="label">{{label}}</label></div>
<div><span class="subLabel">{{subLabel}}</span></div>

注意:上面的代码将仅使用prop isChecked作为初始化程序。如果父级以任何方式更改它传递给isChecked的值,则子组件将不会选择该更改。如果你想拿起它,除了上面提出的代码之外还要添加一个watch

  //...
  watch: {
    isChecked(newIsChecked) {
      this.isCheckedInternal = newIsChecked;
    }
  }
};

Ideal

您的代码有一些可能的改进。以下是一些建议:

  • subLabel道具应该是sub-label
  • 而不是发出changeVal值,发出update:isChecked然后你可以在父母中使用:is-checked.sync="myCheckedValue"

这样你仍然可以在内部绑定到prop isChecked而不是更改它,但是发出事件并对父进行更改isChecked做出反应。

如果你想加倍努力(并且认为值得),你也可以在组件中添加model选项,这样你就可以使用v-model而不是:is-checked.sync

见下面的演示。

Vue.component("ax-checkbox", {
  template: '#axCheckboxTemplate',
  props: {
    label: String,
    subLabel: String,
    size: String,
    isChecked: false,
    checks: []
  },
  model: {       // <== this part to will also enable v-model besides :is-checked.async
    prop: 'isChecked',
    event: 'update:isChecked'
  },
  methods: {
    updateIsChecked() {
      this.$emit("update:isChecked", !this.isChecked);
    }
  }
})
new Vue({
  el: '#app',
  data: {
    myCheckedValueSync: false, myCheckedValueVModel: false,
  }
});
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>

<template id="axCheckboxTemplate">
  <div class="checkBox-container">
    <input type="checkbox" :checked="isChecked" @change="updateIsChecked" />
    <div class="check" :class="[size]" @click="updateIsChecked">
      CLICK ME<div v-if="isChecked">v</div>
    </div>
    <label class="label">{{label}}</label><span class="subLabel">{{subLabel}}</span>
  </div>
</template>

<div id="app">
  <div class="filters">
    <pre>parent's myCheckedValueSync: {{ myCheckedValueSync }}</pre>
    <ax-checkbox label="Où :" sub-label="Ville" size="small" :is-checked.sync="myCheckedValueSync">
    </ax-checkbox>
      
    <pre>parent's myCheckedValueVModel: {{ myCheckedValueVModel }}</pre>
    <ax-checkbox label="Quoi :" sub-label="Thématique(s)" size="small" v-model="myCheckedValueVModel">
    </ax-checkbox>
  </div>
</div>
© www.soinside.com 2019 - 2024. All rights reserved.