我已经在VueJS中创建了一个简单的视图组件,并且遇到了一个非常常见的错误:
避免直接更改道具,因为该值将被覆盖 每当父组件重新渲染时。而是使用数据或 根据属性值计算属性。道具被突变: “值”
这是我的代码:
<template>
<numeric-text-field class="mx-auto" label="Head Mass" units="kg" v-model="turbine.head_mass" />
</template>
<script>
import NumericTextField from '@/components/common/NumericTextField'
export default {
name: 'Turbines',
components: {
NumericTextField
},
data () {
return {
turbine: {}
}
}
}
</script>
<style scoped>
</style>
奇怪的是,我收到修改“值”的错误,但我的代码中没有值。我认为这是由数字文本字段创建的间接层引起的。当我仅使用普通输入文本时,此问题在我的代码中不存在。这里发生了什么?除了v-model,我还有其他特殊方法可以将模型连接到我的数字文本字段吗?
答案 0 :(得分:0)
了解道具在Vue中的工作方式非常重要。这里的关键方面是one-way data flow使用道具。如果希望它是双向数据流,则需要使用v-model
。
话虽如此,您可以通过几种不同的方式进行此操作。我更喜欢将computed properties用于这样的事情!它很干净,并且易于遵循代码。
您应该在numeric-text-field
组件中而不是直接修改道具,而应在
值已更改。这就是您的Turbines.vue
的外观:
<template>
<numeric-text-field class="mx-auto"
label="Head Mass"
units="kg"
:headMass="turbine.head_mass"
v-on:updateHeadMass="updateHeadMass"/>
</template>
<script>
import NumericTextField from '@/components/common/NumericTextField'
export default {
name: 'Turbines',
components: {
NumericTextField
},
data () {
return {
// You should consider initializing your data with the structure that matches what you expect, instead of an empty object
turbine: {
head_mass: ""
}
}
},
methods: {
updateHeadMass(value) {
this.turbines.head_mass = value;
}
}
}
</script>
<style scoped>
</style>
您会注意到v-on:updateHeadMass
属性。这就是我们侦听子组件发出的事件的方式。发出updateHeadMass
偶数后,我们可以调用一个特定的函数并相应地更新父组件中的数据。这将导致子组件发生反应性更改,然后进行更新。
内部NumericTextField
使用一个计算属性,而不是直接修改道具,当输入更改时,该属性会发出事件,直到父组件为止
NumericTextField
组件的外观如下:
<template>
<div>
<label for="headMass">Head Mass</label>
<input type="text" v-model="localHeadMass" name="headMass"/>
</div>
</template>
<script>
export default {
name: "numeric-text-field",
computed: {
localHeadMass: {
get() {
return this.headMass;
},
set(value) {
// Now, anytime we change this property, our parent receives the new value and updates the `headMass` prop!
this.$emit("updateHeadMass", value);
}
}
},
props: {
headMass: {
type: String,
default: "0",
required: true
}
}
};
</script>
<style scoped>
</style>
如果您不喜欢上述方法,可以改用这样的观察器:
<template>
<div>
<label for="headMass">Head Mass</label>
<input type="text" v-model="localHeadMass" v-on:change="updateHeadMass" name="headMass"/>
</div>
</template>
<script>
export default {
name: "numeric-text-field",
data: () => {
return {
localHeadMass: ""
};
},
props: {
headMass: {
type: String,
default: "0",
required: true
}
},
methods: {
updateHeadMass() {
this.$emit("updateHeadMass", this.localHeadMass);
}
},
watch: {
headMass(value) {
this.localHeadMass = value;
}
}
};
</script>
<style scoped>
</style>
答案 1 :(得分:0)
在原始发布时,这对我来说并不为人所知,并在NumericTextField中发布。我以为这是标准的Vueify组件,但是是由同事添加的。如原始帖子的评论所指出的那样,它无法正确处理双向输入。
技巧是像Ohgodwhy建议的那样,从@input的NumericTextField组件中添加this。$ emit('input',value)。