Vue .sync 仅适用于 v-model,但会出现突变错误
Vue .sync only works with v-model, but gives mutation error
// 注意:问题是由于 VueFormulate 的 FormulaInput(自定义输入)造成的。
检查代码沙箱以获得 .sync
的 3 个工作示例
用例
我的应用程序将多个动态组件注入一个视图,然后将每个组件内的多个输入绑定到 parent 中的数据。
由于 v-model
仅适用于单个值,我发现 .sync
(在 Vue 2.3 之后再次添加)是 two-way 在每个输入中绑定多个输入的唯一方法child 我的 parent 数据的组成部分。
问题
我遵循了 Vue 文档和许多教程中的确切语法,但是当我在我的 child 组件中使用 :value="value
时,它在我的数据中输入 undefined
没有错误在控制台中。
如果我使用 v-model
,它会按预期工作,但是每次按下按键都会在控制台中产生 no-mutate-props
错误。
预期结果
我希望 two-way 绑定能够正常工作,而不会在控制台中产生任何 no-mutate-props
错误。
我想我需要某种观察者来检查引用我的 prop 的值,但这看起来有点混乱,而且我必须为大约 30 个组件实现它...我更喜欢一些东西尽可能清洁。
Code Sandbox Example of issue
在Child
// 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
}
}
在Parent
<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/vue@2.6.12"></script>
<div id="app">
<div>
<child :value.sync="foo.bar" />
</div>
<pre v-html="foo" />
</div>
我特意使用了一个嵌套的 属性,它通常不是反应式的。
虽然在这个特定示例中使用它实际上有点冗长(因此它可能不如 Dan 提议的语法有用),但在与 Vuex 状态属性一起使用时会派上用场(在 getter 并在 setter 中提交突变 - 特别是因为您可以将本地计算命名为与状态相同 属性).
值得注意的是,它不需要额外的侦听器(性能提升可以忽略不计)(例如:@input
、@change
、@keydown
等... - 为了完整性,在生产代码中,您可能想添加粘贴事件侦听器,并且可能还有其他边缘情况 - 自动完成!? - 虽然大多数情况都包含在 @input
中。
如您所料,每当 v-model
属性 的值发生变化时,setter 中的代码都会得到一次 运行。总之,就是妥妥的双向绑定。
// 注意:问题是由于 VueFormulate 的 FormulaInput(自定义输入)造成的。
检查代码沙箱以获得 .sync
的 3 个工作示例
用例
我的应用程序将多个动态组件注入一个视图,然后将每个组件内的多个输入绑定到 parent 中的数据。
由于 v-model
仅适用于单个值,我发现 .sync
(在 Vue 2.3 之后再次添加)是 two-way 在每个输入中绑定多个输入的唯一方法child 我的 parent 数据的组成部分。
问题
我遵循了 Vue 文档和许多教程中的确切语法,但是当我在我的 child 组件中使用 :value="value
时,它在我的数据中输入 undefined
没有错误在控制台中。
如果我使用 v-model
,它会按预期工作,但是每次按下按键都会在控制台中产生 no-mutate-props
错误。
预期结果
我希望 two-way 绑定能够正常工作,而不会在控制台中产生任何 no-mutate-props
错误。
我想我需要某种观察者来检查引用我的 prop 的值,但这看起来有点混乱,而且我必须为大约 30 个组件实现它...我更喜欢一些东西尽可能清洁。
Code Sandbox Example of issue
在Child
// 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
}
}
在Parent
<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/vue@2.6.12"></script>
<div id="app">
<div>
<child :value.sync="foo.bar" />
</div>
<pre v-html="foo" />
</div>
我特意使用了一个嵌套的 属性,它通常不是反应式的。
虽然在这个特定示例中使用它实际上有点冗长(因此它可能不如 Dan 提议的语法有用),但在与 Vuex 状态属性一起使用时会派上用场(在 getter 并在 setter 中提交突变 - 特别是因为您可以将本地计算命名为与状态相同 属性).
值得注意的是,它不需要额外的侦听器(性能提升可以忽略不计)(例如:@input
、@change
、@keydown
等... - 为了完整性,在生产代码中,您可能想添加粘贴事件侦听器,并且可能还有其他边缘情况 - 自动完成!? - 虽然大多数情况都包含在 @input
中。
如您所料,每当 v-model
属性 的值发生变化时,setter 中的代码都会得到一次 运行。总之,就是妥妥的双向绑定。