父数据更改时,不会更新VueJS子组件

时间:2017-03-13 17:17:26

标签: javascript data-binding vue.js render vuejs2

我有一个包含多个parent组件的child组件。我希望父组件管理其所有子组件的状态。当孩子被点击时,我希望父母知道,我想更新所有兄弟姐妹,以便他们知道哪一个是活跃的。

JSFIDDLE DEMO

Vue.component('child', {
  template: '#childtemplate',
  props: ['index', 'activeIndex'],
  methods: {
    updateActiveIndex: function() {
      console.log("emitting");
      this.$emit('updateEvent', this.index);
    }
  }
});

Vue.component('parent', {
  data: function() {
    return {
      activeIndex: 0
    }
  },
  render: function(createElement) {
    console.log("rendering ai->", this.activeIndex);

    this.$options._renderChildren.forEach(function(item, index) {
      if (item.data === undefined)
      return;

      item.componentOptions.propsData = {
        index: index,
        activeIndex: this.activeIndex
      }
    }.bind(this));

    return createElement('div', {}, this.$options._renderChildren);
  },
  methods: {
    handleToggle: function(index) {
      this.activeIndex = index;
    }
  },
  created: function() {
    this.$on('updateEvent', this.handleToggle);
    //try manually update it, but the children don't update.
    setTimeout(function(){this.activeIndex = 6}.bind(this), 3000);
  }
});

new Vue({
  el: '#app'
})

我尝试将事件监听器选项添加到parent render()中的createElement函数,如下所示:

return createElement('div', {on:{updateEvent: this.handleToggle}}, this.$options._renderChildren);

我尝试在$on创建的函数中设置parent侦听器。但这并没有触发。

我尝试使用超时手动更新activeIndex,并在根目录上更新它,但不会更新子项。

一个黑客攻击解决方案,我发现唯一可行的方法是直接从传递索引的子进程引用$parent回调,然后在循环访问子进程的父进程中引用并手动分配道具。这会导致vue警告错误,但会完成工作。

有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

我不确定这是否更好,但它适用于此modified fiddle。基本上它会迭代默认的插槽,丢弃任何不是child的内容,设置适当的属性并包含当前每个子插槽中的内容。

render: function(createElement) {
  console.log("rendering ai->", this.activeIndex);

  const children = [];
  for (let i=0; i < this.$slots.default.length; i++){
    if (!(this.$slots.default[i].tag == "child"))
      continue;

    children.push(createElement(Child, {
      props:{
        index: i,
        activeIndex: this.activeIndex
      },
      on:{
        updateEvent: this.handleToggle
      }
    }, this.$slots.default[i].children))

  }

  return createElement('div', {}, children);
}