关联数据更改后,Vue组件不会立即更新

时间:2019-11-29 15:07:13

标签: vue.js vuejs2

我对Vue还是陌生的,我很努力让组件在连接的数据更新后立即更新其内容。该组件将在重新渲染后立即显示更改的内容。

组件

Vue.component('report-summary', {
  props: ['translation', 'store'],
  watch: {
    'store.state.currentModel.Definition': {
      handler: function(change) {
        console.log('Change detected', change);
      },
      deep:true
    }
  },
  template: '<div>
    '<div class="alert alert-secondary" role="alert">' +
    '<h5 class="border-bottom border-dark"> {{ translation.currently_defined }}</h5>' +
    '<div>{{ store.state.currentModel.Definition.length }} {{translation.elements }}</div>' +
    '</div>' +
    '</div>'
});

store作为页面HTML中的属性传递:

<report-summary :translation="t" :store="store"></report-summary>

store本身是Vuex.Store

let store = new Vuex.Store({
  state: {
    t: undefined,
    currentModel: undefined
  },
  mutations: {
    storeNewModel(state) {
      let model = CloneFactory.sealedClone(
        window.Project.Model.ReportTemplateModel);
      model.Header = CloneFactory.sealedClone(
        window.Project.Model.ReportTemplateHeaderModel);
      state.currentModel = model;
    },
    storeNewModelDefinition(state, definition) {
     state.currentModel.Definition.push(definition);
    }
  }
});

在将任何数据存储在模型的currentModel属性中之前,通过调用store.commit('storeNewModel');初始化Definition元素。

通过循环使用store.commit('storeNewModelDefinition')更新定义的内容:

for (let c in this.$data.currentDefinition.charts) {
  store.commit('storeNewModelDefinition', c);
}

调用store.commit('storeNewModelDefinition', c);时,商店将按预期进行更新:

Vuex%20Store|325x190

但是组件不会对更改的数据做出反应:

Not%20updated|553x110

然后当我离开(通过更改隐藏嵌入式组件的视图)并再次导航到该视图时,内容已更新:

updated|476x112

在“控制台”窗口中,我看到观察者在任何时间都没有被触发:

console|681x133

我在这里想念什么?非常感谢您提前睁开眼睛。

使用EventBus

watch切换到事件总线侦听器也没有按计划进行。

这是EventBus的初始化:

window.eventBus= new Vue(); 

我将此添加到了我的组件中

  created: function() {
    window.eventBus.$on('report-summary-update', function() {
      this.$nextTick(function(){ this.$forceUpdate(); });
    });
  }

并在列表中添加或删除元素后发出事件:

window.eventBus.$emit('report-summary-update');

在调试器中观察this.$forceUpdate();设置断点时,我看到它也在被调用,但是UI仍将显示旧内容,而没有任何更改。我现在真的迷路了。


P.S。我将其交叉发布在Vue forum上,但是由于社区希望在这里获得一些反馈的希望很小。

3 个答案:

答案 0 :(得分:2)

将数据推送到嵌套数组总是会导致组件无法更新的此类问题。

尝试向您的商店中添加吸气剂,并使用该吸气剂从商店中获取数据

let store = new Vuex.Store({
  state: {
    t: undefined,
    currentModel: undefined
  },
  mutations: {
    storeNewModel(state) {
      let model = CloneFactory.sealedClone(
        window.Project.Model.ReportTemplateModel);
      model.Header = CloneFactory.sealedClone(
        window.Project.Model.ReportTemplateHeaderModel);
      state.currentModel = model;
    },
    storeNewModelDefinition(state, definition) {
     state.currentModel.Definition.push(definition);
    }
  },
  getters:{
    definitions(state){
      return state.currentModel.Definition
    }
  }
});

在您的组件中,您可以添加一个从商店获取数据的计算道具

Vue.component('report-summary', {
  props: ['translation', 'store'],
  computed: {
    definitions(){
     return store.getters.definitions
    }
  },
  template: '<div>
    '<div class="alert alert-secondary" role="alert">' +
    '<h5 class="border-bottom border-dark"> {{ translation.currently_defined }}</h5>' +
    '<div>{{ definitions.length }} {{translation.elements }}</div>' +
    '</div>' +
    '</div>'
});

更新(2019年11月30日) 如果上面的代码仍然不起作用,请将您的storeNewModelDefinition突变更改为此:

storeNewModelDefinition(state, definition) {
     // Create a new copy of definitions
     let definitions = [...state.currentModel.Definition]

     // Push the new item
     definitions.push(definition)

     // Use `Vue.set` so that Vuejs reacts to the change
     Vue.set(state.currentModel, 'Definition', definitions);
    }

答案 1 :(得分:1)

仅在您的EventBus实验上做一个笔记(您绝对应该尝试解决反应性问题,而不要尝试类似$forceUpdate之类的技巧)

为什么您对EventBus的实验不起作用是因为使用匿名函数作为事件处理程序。看一下这段代码:

  methods: {
    onEvent() {
      console.log(this)
    }
  },
  mounted() {
    // this.onEvent is method where "this" is bound to current Vue instance
    this.$bus.$on("test", this.onEvent);
    // Handler is anonymous function - "this" refers to EventBus Vue instance
    this.$bus.$on("test", function() {
      console.log(this)
    });
  }
  • 1t事件处理程序是一个函数,其中this被Vue本身显式绑定(由Vue自身绑定)到处理程序“存在”的Vue实例
  • 第二个事件处理程序是匿名函数,this未显式绑定,因此最终类似于this == event bus Vue instance。您可以使用闭包来解决此问题:
  mounted() {
    let self = this;
    this.$bus.$on("test", function() {
       // self = "this" in context of function "mounted"
       console.log(self)
    });
  }
JS中的

this可能很棘手...

答案 2 :(得分:0)

摘自vuejs文档“深度反应”部分

  

数据对象中必须存在属性,以便Vue对其进行转换并使其具有反应性

这是一次性的Vue反应性警告。 Vue无法检测到属性的添加或删除。

以您的状态而不是currentModel: undefined来添加您希望进行反应的所有属性,例如

currentModel: { definitions:[] }

然后从definitions数组中添加或删除任何元素都会自动变为反应性。

您可以在文档中找到更多说明

Reactivity in depth

Change detection caveats