Vuejs - 如何在作用域插槽中传递父和子之间的更改

时间:2017-05-02 08:13:16

标签: javascript vue.js vuejs2

我正在尝试创建一个有两个插槽的组件。第二个插槽基于第一个插槽中的项目数重复。我使用作用域插槽实现了这一点,但是,当在第一个插槽上更新数据时,第二个插槽在触发事​​件之前不会自动更新它,例如:单击调用方法的按钮。

当在第一个插槽上更改数据时,有没有办法让第二个插槽更新其视图?

以下是我的例子:

Jsfiddle:https://jsfiddle.net/89vykm75/1/

new Vue({
	el: '#app',
  components: {
  	'repeat-for-each-item': {
      data: function() {
          return {
              items: []
          }
      },
    	template: `<div>
          <slot name="item" v-for="item in items" :item="item"></slot>
          <button @click="addItem()">Add item</button>
          <slot name="repeat" v-for="item in items" :item="item"></slot>
      </div>
      `,
      methods: {
        addItem() {
          this.items.push({});
        }
      }
    }
  }
});
<div id="app">
  <repeat-for-each-item>
    <template slot="item" scope="props">
      <div>
        <input type="text" v-model="props.item.name">
      </div>
    </template>
    
    <template slot="repeat" scope="props">
      <div>
        <label>
            <span v-if="props.item.name">{{props.item.name}}:</span>
            <span v-else>No Name:</span>
        </label>
        <input type="text">
      </div>
    </template>
  </repeat-for-each-item>
</div>

2 个答案:

答案 0 :(得分:2)

我通过调用keyup上的方法找到了解决方案。

基本上,我在插槽

上添加了@keyup事件
<input type="text" v-model="props.item.name" @keyup="props.onchange()">

在组件模板上,将onchange方法传递给插槽

<slot name="item" v-for="item in items" :item="item" :onchange="onchange"></slot>

然后使用onchange函数强制重新渲染

onchange:() => {
    // hack to trigger changes
    this.$set(this.items, 0, this.items[0]);
}

以下是完整工作的JsFiddle:https://jsfiddle.net/89vykm75/2/

我想知道是否有更清洁的解决方案?

答案 1 :(得分:2)

你正陷入Vue change detection caveat。这里的问题是,如果在将对象添加到Vue数据之前向对象添加属性,则Vue无法检测到更改。这是问题所在:

this.items.push({})

您正在添加没有属性的对象,然后将v-model绑定到该对象的name属性,该属性不存在。 Vue无法检测到更改,也不会更新绑定到该属性的其他项。

如果您改为这样做:

this.items.push({name: null})

您会发现您的代码有效。这是更新后的fiddle