避免改变道具:vuejs 2

时间:2018-03-01 14:42:14

标签: vue.js vuejs2

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

PARENT: 模板:

$(document).ready(function() {
    var x = 0;
    $('#score_list > li').each(function(a){
    x = x + +$(this).data('score')
  })
  console.log(x)
});

脚本:

<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");
    }
  }
};

2 个答案:

答案 0 :(得分: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;
    }
  }
};

理想

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

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

通过这种方式,您仍然可以在内部绑定到道具isChecked而不会更改它,但会发出事件并对父级更改isChecked时做出反应。

如果您想加倍努力(并认为值得),您还可以在组件中添加model选项,这样您就可以使用v-model代替{ {1}}。

见下面的演示。

&#13;
&#13;
:is-checked.sync
&#13;
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,
  }
});
&#13;
&#13;
&#13;

答案 1 :(得分: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); }

  3. 如果需要,您仍然可以发出changeVal事件。