【问题标题】:Why an addition of a key does not trigger a watched variable? [duplicate]为什么添加键不会触发监视变量? [复制]
【发布时间】:2018-09-28 21:03:57
【问题描述】:

我有一个对象allevents 异步更新了键和值。每当修改allevents 时,我想触发重新计算功能。

为此,我使用了以下 Vue 结构(在一个组件中,删除了所有不相关的元素):

export default {
        data: function () {
            return {
                //
                allevents: {},
                events: []
            }
        },
        methods: {
            //
            mqttMessage(topic, message) {
                const cal = topic.split('/').pop()
                this.allevents[cal] = JSON.parse(message).filter(x => true)
                // following the update above, I was expecting that since 
                // allevents is watched below, the function would trigger
                // as a workaround, I added this line below which fixes the issue
                // but I still would like to understand the lack of trigger
                this.computeEvents()
            },
            // the function ssupposed to be triggred after a chnage, below
            computeEvents() {
                this.events = []
                Object.values(this.allevents).forEach(cal => cal.forEach(e => this.events.push(e)))
            }
        },
        watch: {
            // whenever allevents change, run computeEvents() <-- this does not happen
            allevents() { 
                console.log("events compute triggered")
                this.computeEvents() 
            }
        },
        mounted() {
            //
        }
}

即使allevents 被修改并被监视,computeEvents() 也不会启动。为什么?

【问题讨论】:

标签: vue.js vue-component


【解决方案1】:

您似乎是Reactivity/Change Detection Caveat 的受害者。

代替:

this.allevents[cal] = JSON.parse(message).filter(x => true)

试试:

Vue.set(this.allevents, cal, JSON.parse(message).filter(x => true))

或者:

this.$set(this.allevents, cal, JSON.parse(message).filter(x => true))

来自the docs的相关摘录:

变更检测注意事项

由于现代 JavaScript 的局限性(以及放弃 Object.observe),Vue 无法检测到属性添加或 删除。由于Vue执行getter/setter转换过程 在实例初始化期间,属性必须存在于 data 对象,以便 Vue 转换它并使其具有反应性。为了 示例:

var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` is now reactive
vm.b = 2
// `vm.b` is NOT reactive

Vue 不允许动态添加新的根级响应式 属性到已经创建的实例。然而,有可能 使用Vue.set(object, key, value) 方法向嵌套对象添加反应属性:

Vue.set(vm.someObject, 'b', 2)

您也可以使用vm.$set 实例方法,它是 全球Vue.set

this.$set(this.someObject, 'b', 2)

【讨论】:

  • 什么是someObject
  • @adelriosantiago 是data 中的属性的名称。在示例中,a 就是这样一个属性(尽管它是一个数字,并且只有在 a 是一个对象时,set 调用才有意义)。
猜你喜欢
  • 2012-12-23
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多