我有两个<select>
元素。当我在第一个中选择一个值时,我想默认第二个的值。它适用于v-model
,但不适用于:value
。
一个是车辆清单。
<select :value="vehicle" @change="setVehicle($event.target.value)">
<option value="CAR">Car</option>
<option value="PLANE">Plane</option>
</select>
另一个是零件清单。仅当选择WINGS
时,PLANE
部分才可见。
<select :value="part" @change="setPart($event.target.value)">
<option value="ENGINE">Engine</option>
<option value="WINDOWS">Wheels</option>
<option v-if="vehicle === 'PLANE'" value="WINGS">Wings</option>
</select>
车辆的设置器很简单,但是飞机的默认零件是有条件渲染的WINGS
。
setVehicle: function(newVehicle) {
this.vehicle = newVehicle;
if (this.vehicle === "PLANE") {
this.part = "WINGS";
} else {
this.part = "ENGINE";
}
}
无功part
数据设置为正确的值,例如您可以用{{ part }}
显示它,但是<select>
元素未正确更新。如果我将零件的选择更改为使用v模型,则效果很好:
<select v-model="part">
使用v模型是不可接受的解决方法,因为在我的实际应用中,part
是只读的,并且只能使用setter进行更改(使用类似商店的体系结构)。另一个解决方法是在setVehicle设置器中使用setTimeout(.., 1)
。我真的不喜欢这种解决方案。我真正想知道的是,当文档显示v-model
只是语法糖时,为什么:value/@change
的行为不同于v-model
。
演示:https://codesandbox.io/s/eager-liskov-2yor4?file=/src/App.vue
由于第三个选项不在DOM中,而您在更新this.part时,当时未选择它。因此,您有两个选择:
1)使用nextTick()等待组件更新,然后设置新值:
setVehicle: function(newVehicle) {
this.vehicle = newVehicle;
this.$nextTick(()=>{
if (this.vehicle === "PLANE") {
this.part = "WINGS";
} else {
this.part = "ENGINE";
}
})
}
或
2)保留第三个选项,但在车辆为汽车时将其隐藏。这样,它将在更换车辆时被选择,并在稍后显示DOM更新时显示。您将通过v-show而不是v-if来进行此操作。
<select :value="part" @change="setPart($event.target.value)">
<option value="ENGINE">Engine</option>
<option value="WINDOWS">Wheels</option>
<option v-show="vehicle === 'PLANE'" value="WINGS">Wings</option>
</select>
这是我的解决方案。基本上,您不应该担心v模型。将这些值复制到组件本身,然后根据需要使用它们。
但是我同意。 :value行为异常,即使使用.sync属性也是如此。 (我怀疑这是因为将属性工具设置为PLANE,并且在设置零件WINGS之后立即生成v-if渲染。但不是很确定。)