无渲染组件中的 v-model
v-model inside a renderless component
代码沙箱:https://codesandbox.io/s/61my3w7xrw?fontsize=14
我有这个使用范围插槽的无渲染组件:
name: "BlockElement",
props: {
element: {
type: Object,
required: true
}
},
data() {
return {
inputValue: this.element.value
};
},
render() {
return this.$scopedSlots.default({
inputName: this.inputName,
inputValue: this.inputValue
});
}
像这样使用它:
<block-element :element="element" v-slot="{ inputName, inputValue }">
<div>
<input type="text" :name="inputName" v-model="inputValue">
<p>inputValue: {{ inputValue }}</p>
</div>
</block-element>
... 所以值不会在更改时更新。我做错了什么?
在模板的以下部分
<input type="text" :name="inputName" v-model="inputValue">
inputValue
是从 v-slot
而不是 inputValue
在 <block-element>
组件上计算的 属性 获得的变量;所以如果你分配给它(这是 v-model
所做的)它不会调用 setter,它只是在模板代码中设置局部变量的值。
你可以"fix"这样:
<block-element :element="element" v-slot="{ inputName }" ref="block">
<div>
<input type="text" :name="inputName" v-model="$refs.block.inputValue">
<p>inputValue: {{ $refs.block.inputValue }}</p>
</div>
</block-element>
但这太乱了,破坏了你试图创建的抽象。
另一种方法是在范围对象上设置 inputValue
setter 属性 以正确地将更新委托给组件:
render() {
const self = this;
return this.$scopedSlots.default({
inputName: this.inputName,
get inputValue() { return self.inputValue },
set inputValue(value) { self.inputValue = value; },
});
}
<block-element :element="element" v-slot="scope">
<div>
<input type="text" :name="scope.inputName" v-model="scope.inputValue">
<p>inputValue: {{ scope.inputValue }}</p>
</div>
</block-element>
但这也不理想,因为范围对象通常不可写,并且需要记录这个特定的实现细节。
在这种情况下,您希望作用域插槽将数据传回父组件,您可以通过将回调函数传递给插槽来实现。您可以提供设置 inputValue
的功能,但您不能使用 v-model
:
render() {
return this.$scopedSlots.default({
inputName: this.inputName,
inputValue: this.inputValue,
setInputValue: value => this.inputValue = value,
});
}
<block-element :element="element" v-slot="{ inputName, inputValue, setInputValue }">
<div>
<input type="text" :name="inputName" :value="inputValue" @input="setInputValue($event.target.value)">
<p>inputValue: {{ inputValue }}</p>
</div>
</block-element>
现在再也不用为做什么而感到困惑了。
代码沙箱:https://codesandbox.io/s/61my3w7xrw?fontsize=14
我有这个使用范围插槽的无渲染组件:
name: "BlockElement",
props: {
element: {
type: Object,
required: true
}
},
data() {
return {
inputValue: this.element.value
};
},
render() {
return this.$scopedSlots.default({
inputName: this.inputName,
inputValue: this.inputValue
});
}
像这样使用它:
<block-element :element="element" v-slot="{ inputName, inputValue }">
<div>
<input type="text" :name="inputName" v-model="inputValue">
<p>inputValue: {{ inputValue }}</p>
</div>
</block-element>
... 所以值不会在更改时更新。我做错了什么?
在模板的以下部分
<input type="text" :name="inputName" v-model="inputValue">
inputValue
是从 v-slot
而不是 inputValue
在 <block-element>
组件上计算的 属性 获得的变量;所以如果你分配给它(这是 v-model
所做的)它不会调用 setter,它只是在模板代码中设置局部变量的值。
你可以"fix"这样:
<block-element :element="element" v-slot="{ inputName }" ref="block">
<div>
<input type="text" :name="inputName" v-model="$refs.block.inputValue">
<p>inputValue: {{ $refs.block.inputValue }}</p>
</div>
</block-element>
但这太乱了,破坏了你试图创建的抽象。
另一种方法是在范围对象上设置 inputValue
setter 属性 以正确地将更新委托给组件:
render() {
const self = this;
return this.$scopedSlots.default({
inputName: this.inputName,
get inputValue() { return self.inputValue },
set inputValue(value) { self.inputValue = value; },
});
}
<block-element :element="element" v-slot="scope">
<div>
<input type="text" :name="scope.inputName" v-model="scope.inputValue">
<p>inputValue: {{ scope.inputValue }}</p>
</div>
</block-element>
但这也不理想,因为范围对象通常不可写,并且需要记录这个特定的实现细节。
在这种情况下,您希望作用域插槽将数据传回父组件,您可以通过将回调函数传递给插槽来实现。您可以提供设置 inputValue
的功能,但您不能使用 v-model
:
render() {
return this.$scopedSlots.default({
inputName: this.inputName,
inputValue: this.inputValue,
setInputValue: value => this.inputValue = value,
});
}
<block-element :element="element" v-slot="{ inputName, inputValue, setInputValue }">
<div>
<input type="text" :name="inputName" :value="inputValue" @input="setInputValue($event.target.value)">
<p>inputValue: {{ inputValue }}</p>
</div>
</block-element>
现在再也不用为做什么而感到困惑了。