我有一个支持 v-model
的自定义组件。组件内部值的表示与原始输入完全不同,但在组件内部使用很方便。组件的职责是转换值并让用户以复杂的形式改变它。此外,组件应该响应父组件的 v-model
更改,即它应该监视 value
更改。
我的代码:
export default {
props: ['value'],
data() {
return {innerValue: undefined};
},
mounted() {
this.calculateInnerValue();
},
methods: {
calculateInnerValue() {
this.innerValue = /* very heavy transformation based on this.value */;
},
onUserChange() {
const value = /* very heavy transformation based on this.innerValue */;
this.$emit('input', value);
}
},
watch: {
value() {
this.calculateInnerValue();
}
}
}
问题是,每当该组件触发 input
事件时, watch 就会被触发,从而导致不必要的 calculateInnerModel
调用。
是否有一种好方法可以防止这种行为,同时保持对来自其他来源的父值更改的响应?
我可以想出一个标志,例如
calculateInnerValue() {
if (!this.itsMeChanging)
this.innerValue = /* very heavy computation based on this.value */;
},
onChange() {
const value = /* very heavy computation based on this.innerValue */;
this.itsMeChanging = true;
this.$emit('input', value);
this.itsMeChanging = false;
}
但是,正如您所看到的,这是 nice 的 faaaar。
Github 上稍微相关的问题:https://github.com/vuejs/vue/issues/1829
最佳答案
您可以做的一件事是保留对未转换的 value
属性的引用,然后仅在 value
中的情况下调用 calculateInnerValue
方法观察者与子组件的引用不同。
下面是一个示例,其中 innerValue
现在对应于从父级传入的 value
属性的未转换值,并且转换后的值现在设置为 TransformedValue
数据属性:
export default {
props: ['value'],
data() {
return {
innerValue: this.value,
transformedValue: undefined
};
},
mounted() {
this.calculateTransformedValue();
},
methods: {
calculateTransformedValue() {
this.transformedValue = /* very heavy transformation based on this.innerValue */;
},
onUserChange() {
this.innerValue = /* very heavy transformation based on this.transformedValue */;
this.$emit('input', this.innerValue);
}
},
watch: {
value(value) {
if (value !== this.innerValue) {
this.calculateTransformedValue();
this.innerValue = value;
}
}
}
}
您还可以通过使 transformedValue
成为基于 innerValue
的计算属性来进一步简化代码:
export default {
props: ['value'],
data() {
return {
innerValue: this.value
};
},
computed: {
transformedValue() {
return /* very heavy transformation based on this.innerValue */
}
},
methods: {
onUserChange() {
this.innerValue = /* very heavy transformation based on this.transformedValue */;
this.$emit('input', this.innerValue);
}
},
watch: {
value(value) {
this.innerValue = value;
}
}
}
关于vue.js - 不要看v-model自己的更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57463191/