这是我运行代码时控制台中出现的内容:“避免直接改变道具,因为只要父组件重新渲染,该值就会被覆盖。而是根据道具的值使用数据或计算属性。支持变异: “器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>
由于您似乎正在尝试更新传递到组件中的属性的值,因此您的组件实际上是一个自定义输入组件。看看excellent Vue docs on this topic。我总结了下面的想法。
Vue中的双向数据绑定由v-model
处理。应用于您的isChecked属性,这归结为v-model="isChecked"
,实际上是:value="isChecked" @input="evt => isChecked = evt.target.value"
的语法糖。
因此,对于您的组件,您需要执行以下操作:
isChecked
属性的名称更新为value
changeVal
方法中,发出一个输入事件,如:
changeVal() { this.$emit("input", !this.value); }
如果需要,你仍然可以发出changeVal
事件。
你变异的道具是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"
。这样你仍然可以在内部绑定到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>