我有一个支持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事件,就会触发监视,从而导致不需要的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;
}

但是,正如您所看到的,这很好。

Github上的相关问题:https://github.com/vuejs/vue/issues/1829

最佳答案

您可以做的一件事是保留对未转换的value属性的引用,然后仅在观察器中的calculateInnerValue与子组件的引用不同的情况下才调用value方法。

这是一个示例,其中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模型更新,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57463191/

10-12 04:27