Vue.js 不要观看自己的v-model更新

Vue.js 不要观看自己的v-model更新,vue.js,vuejs2,vue-component,Vue.js,Vuejs2,Vue Component,我有一个支持v-model的自定义组件。组件内的值表示与原始输入完全不同,但便于在组件内使用。组件的职责是转换值,并让用户以复杂的形式对其进行更改。此外,组件应响应来自父组件的v-model的变化,即应注意值的变化 我的代码: export default { props: ['value'], data() { return {innerValue: undefined}; }, mounted() { this.calculat

我有一个支持
v-model
的自定义组件。组件内的值表示与原始输入完全不同,但便于在组件内使用。组件的职责是转换值,并让用户以复杂的形式对其进行更改。此外,组件应响应来自父组件的
v-model
的变化,即应注意
值的变化

我的代码:

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();
        }
    }
}
问题在于,每当此组件触发
输入
事件时,就会触发监视,从而导致不必要的
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;
}
但是,正如你所看到的,这是来自尼斯的faaaar


Github上的一个稍微相关的问题:

您可以做的一件事是保留对未转换的
属性的引用,然后仅在watcher中的
值与子组件的引用不同时调用
calculateInnerValue
方法

下面是一个示例,
innerValue
现在对应于从父级传入的
value
prop的未转换值,转换后的值现在设置为
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;
            }
        }
    }
}

您还可以通过基于
innerValue
transformedValue
作为计算属性来进一步简化代码:

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;
        }
    }
}

可以在父组件内部进行转换吗?这样子组件将只输出值并在userChangeIt上发出更改,这将违反SRP。这样做可以很好地封装组件内部的细节,而父级和此无关。但是要注意对象突变(如果
是一个对象)。正确,这假设
属性不是一个对象。在我的例子中,值是一个数组。。。对象类型:-)组件在前端以舒适的方式收集许多类似的项,然后将它们转换为模型形式,然后将它们传递给父对象。但这应该一直有效,直到引用发生变化。谢谢你的主意。