Vue 中的计算属性不会触发监视

Posted

技术标签:

【中文标题】Vue 中的计算属性不会触发监视【英文标题】:Computed property in Vue is not triggering a watch 【发布时间】:2018-12-29 18:32:48 【问题描述】:

根据this post,观察计算属性应该不是问题。然而我的代码却不能正常工作。

<template>
    <div v-if="product" class="section">
        <form>
            <div class="control"><input type="text" class="input" v-model="title"></div>
            <div class="control"><input type="text" class="input" v-model="description"></div>
        </form>
    </div>
</template>

<script>
export default 
    data() 
        return 
            title: null,
            description: null
        
    ,
    computed: 
        product() 
            // const payload =  collection: 'products', id: this.$route.params.productId 
            // return this.$store.getters.objectFromId(payload)
            console.log('working')
            return  title: 'Awesome Title', description: 'Awesome Description' 
        
    ,
    watch: 
        product() 
            this.title = this.product.title,
            this.description = this.product.description
        
    

</script>

我希望watchproduct 返回时触发,但它没有。

我可以像这样在计算属性中设置属性:

computed: 
    product() 
        const payload =  collection: 'products', id: this.$route.params.productId 
        const product = this.$store.getters.objectFromId(payload)
        this.title = product.title
        this.description = product.description
        return product
    

但是编译器给了我一个警告:error: Unexpected side effect in "product" computed property

【问题讨论】:

你想达到什么目的?您的问题可能有更直接的解决方案 我已更新我的帖子以更清楚地显示意图。我正在尝试获取产品并设置一些绑定到某些表单输入的初始数据()。我可以在计算函数中设置值,但我在编译器中收到了这个烦人的副作用警告。我认为在 get 中设置属性是不好的做法? 您需要设置use a watcher 并设置immediate 才能让您的观察者在初始渲染时触发。 @HamishJohnson 您不为此使用计算。看看创建/安装的 vue.js 钩子。在它们内部,您可以加载外部数据并将其附加到当前数据模型 @Enrico 是的,我必须同意你的观点——不太清楚为什么我在这种情况下选择了计算。谢谢 【参考方案1】:

尝试以下方法:

watch: 
    product: 
        immediate: true,
        handler(value)  
            updateCode();
        
    

【讨论】:

【参考方案2】:

根据 OP 的 cmets,他的意图是获取和加载一些初始数据。 实现此行为的常用方法是将其放在 created or mounted vuejs 生命周期钩子中。

<template>
    <div v-if="product" class="section">
        <form>
            <div class="control"><input type="text" class="input" v-model="title"></div>
            <div class="control"><input type="text" class="input" v-model="description"></div>
        </form>
    </div>
</template>

<script>
export default 
    data() 
        return 
            title: '',
            description: ''
        
    ,

    created() 
        this.getInitialData();
        this.foo();

        console.log("created!");
    ,

    methods: 
        getInitialData: function()
            const payload = 
                collection: 'products', 
                id: this.$route.params.productId 
            ;
            var product = this.$store.getters.objectFromId(payload);
            this.title = product.title;
            this.description = product.description;
        ,
        foo: function()// ...
    ,

</script>

【讨论】:

【参考方案3】:

你的结构有点乱。 product 是一个计算值,因此只要它的源值发生变化,它就会运行。 (你无法控制它何时运行。)它不应该有副作用(分配this.descriptionthis.title)或触发网络请求。

product 中的代码正在获取您的源数据。这属于methods,明确链接到用户操作或生命周​​期事件。

为什么需要复制数据(watch:product 中的this.description = product.description)?当你的数据(你的应用程序状态)在 Vue 之外时,Vue 工作得最好,在一个全局变量中。然后,您的 Vue 组件将透明地反映应用程序在给定时刻的状态。

希望这会有所帮助。

【讨论】:

以上是关于Vue 中的计算属性不会触发监视的主要内容,如果未能解决你的问题,请参考以下文章

Vue中的计算属性与监视属性

Vue基础(中):数据代理事件处理计算和监视属性class与style绑定

Vue计算属性

VUE前进之路使用数据代理,计算属性与监视属性的妙用

vue的计算和监视属性,附一小实例

Vue--》计算属性与监视(侦听)属性的使用