我理解Vue 2.3中返回的.sync
修饰符,并将其用于实现“多项选择”的简单子组件。问题和答案。父组件像这样调用子:
<question
:stem="What is your favourite colour?"
:options="['Blue', 'No, wait, aaaaargh!']
:answer.sync="userChoice"
>
父级有一个字符串数据元素userChoice
来存储子组件的结果。孩子为选项提供问题和单选按钮。孩子的基本部分看起来像这样(我使用的是Quasar,因此q-radio
):
<template>
<div>
<h5>{{stem}}</h5>
<div class="option" v-for="opt in options">
<label >
<q-radio v-model="option" :val="opt.val" @input="handleInput"></q-radio>
{{opt.text}}
</label>
</div>
</div>
</template>
export default {
props: {
stem: String,
options: Array,
answer: String
},
data: () => ({
option: null
}),
methods: {
handleInput () {
this.$emit('update:answer', this.option)
}
}
}
这一切都运行良好,除了如果父然后因应用程序中发生的其他事情而更改userChoice
的值这一事实,孩子不会这样做更新单选按钮。我必须在孩子中加入watch
:
watch: {
answer () {
this.option = this.answer
}
}
但感觉有点多余,我担心发布事件来更新父母的数据实际上会导致孩子看到&#39;事件也开火了。在这种情况下,除了浪费几个周期之外它没有任何影响,但如果它记录或计算任何东西,那将是误报......
也许这是真正的双向绑定的正确解决方案(即动态父→子,以及子→父)。我是否错过了如何连接&#39; in&#39;和&#39; out&#39;双方的数据?
如果你想知道,父母想要改变用户选择的最常见情况是&#39;将回应一个明确的答案&#39;将userChoice
设置回空字符串的按钮。这应该具有“不设置”的效果。所有的单选按钮。
答案 0 :(得分:3)
你的构造有一些奇怪的东西不起作用,但如果你把它传播到发生变化的answer.sync
组件,基本上q-radio
就可以了。正确处理更改父级中的答案,但是要清除值,似乎需要将其设置为对象而不是null(我认为这是因为它需要可分配)。
更新
您options
的设置是值得注意的事情。
我在answer
中使用q-radio
来控制其检查状态(v-model
在广播中有特殊行为,这就是我将value
与{{{{{{ 1}})。从您的评论中,v-model
看起来希望拥有一个可以设置的值。您应该能够使用q-radio
基于answer
进行计算,而不是使用option
数据项:get
返回answer
,{ {1}}执行set
。我已更新了我的代码段以使用emit
支持val
加上我描述的计算机。 q-radio
会发出proxyAnswer
事件,这是update
修饰符想要的事件。我还使用代理计算实现了.sync
,但这只是为了让应该已经烘焙的行为进入q-radio
。
(我所描述的实际上是你对数据项和观察者所做的事情,但计算机是一种更好的方法来封装它。)
q-radio
new Vue({
el: '#app',
data: {
userChoice: null,
options: ['Blue', 'No, wait, aaaaargh!'].map(v => ({
value: v,
text: v
}))
},
components: {
question: {
props: {
stem: String,
options: Array,
answer: String
},
computed: {
proxyAnswer: {
get() {
return this.answer;
},
set(newValue) {
this.$emit('update:answer', newValue);
}
}
},
components: {
qRadio: {
props: ['value', 'val'],
computed: {
proxyValue: {
get() {
return this.value;
},
set(newValue) {
this.$emit('input', newValue);
}
}
}
}
}
}
},
methods: {
clearSelection() {
this.userChoice = {};
}
}
});