问题描述
// 注意:问题是由 VueFormulate 的 FormulaInput(自定义输入)引起的。
检查代码沙箱以获取 .sync
的 3 个工作示例
用例
我的应用将多个动态组件注入到一个视图中,然后将每个组件内的多个输入绑定到父级中的数据。
由于 v-model
仅适用于单个值,我发现 .sync
(在 Vue 2.3 之后再次添加)是将每个子组件中的多个输入双向绑定到我的父母的数据。
问题
我遵循了 Vue 文档和许多教程中的确切语法,但是当我在我的子组件中使用 :value="value
时,它在我的数据中输入了 undefined
,控制台中没有错误。
如果我使用 v-model
,它会按预期工作,但是每次按下按键都会在控制台中产生 no-mutate-props
错误。
预期结果
我希望双向绑定不会在控制台中产生任何 no-mutate-props
错误。
我想我需要某种观察者来检查引用我的道具的值,但这似乎有点混乱,我必须为大约 30 个组件实现它......如果可能。
Code Sandbox Example of issue
在孩子
// input1
<input
type="text"
:value="value" <----- this will work if I make it a v-model,but produces mutation error in console
@input="$emit('update:value',value)"
/>
// input2
<input
type="text"
:value2="value2" <----- again,will work with v-model only
@input="$emit('update:value2',value2)"
/>
props: {
value: {
type: String
},value2: {
type: String
}
}
在父级
<component
:is="step.component"
:value.sync="step.value"
:value2.sync="step.value2"
:value3.sync="step.value3"
/>
解决方法
value
不起作用的原因仅仅是因为您发出了相同的未更改的 value
,它被传递了下来。如果没有 v-model
,value
不会发生任何变化,因此没有任何新内容可以发送。
将该输入更改为:
<input
:value="value"
@input="$emit('update:value',$event.target.value)"
type="text"
step="1"
placeholder="Child Input1 (value)"
/>
这样,当输入事件发生时,您从输入框中发出一个新值。
,为了完整起见,我想在 Dan 的回答中添加一个通用的替代方案:一个 Vue 模式,它允许将 v-model
与任何不能直接改变的东西一起使用:computed getter + setter。
概念证明:
Vue.component('child',{
template: `
<input v-model="local" type="text" />
`,props: ['value'],computed: {
local: {
get() {
return this.value;
},set(value) {
this.$emit('update:value',value);
}
}
}
})
new Vue({
el: '#app',data: () => ({
foo: {
bar: 'baz'
}
})
})
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<div id="app">
<div>
<child :value.sync="foo.bar" />
</div>
<pre v-html="foo" />
</div>
我特意使用了一个嵌套属性,它通常不是响应式的。
虽然在这个特定的例子中使用它确实有点冗长(所以它可能没有 Dan 提出的语法有用)它在与 Vuex 状态属性一起使用时可以派上用场(在 getter 中获取 store 值并提交setter 中的突变 - 特别是因为您可以将本地计算命名为与 state 属性相同的名称)。
值得注意的是,它不需要额外的监听器(这是一个可以忽略不计的性能提升)(例如:@input
、@change
、@keydown
等... - 为了完整性,在您可能希望在粘贴事件侦听器中添加生产代码,并且可能还有其他边缘情况 - 自动完成!? - 尽管 @input
涵盖了大多数情况)。
正如您所期望的,每次 v-model
属性的值发生变化时,setter 中的代码都会运行一次。简而言之,这是一个适当的双向绑定。