如何让父母知道插槽内的子组件?

时间:2018-01-08 23:10:56

标签: javascript vue.js vuejs2 vue-component

我想知道如何让父组件知道插槽中的子组件。

例如,如果我想创建一个滑块,我想拥有以下结构:

在我看来:

<vue-slider>
    <vue-slide name="First slide!">First slide content</vue-slide>
    <vue-slide name="Second slide!">Second slide content</vue-slide>
</vue-slider>

VueSlider.vue

<template>
    <div class="slider">
        <ol>
            <li v-for="(slide,index) in slides">{{slide.name}}</li>
        </ol>


        <slot></slot>
    </div>
</template>

<script>
    export default {

        data: function(){
          return {
              slides: [],
          }
        }
    }
</script>

VueSlide.vue

<template>
    <div class="slide">
        <slot></slot>
    </div>
</template>

<script>
    export default {
        props: {
            'name': {

            }
        }
    }
</script>

所以我想填充父组件上的slides数组。我正在考虑在安装每张幻灯片时发出一个事件,但后来我在vue docs上看到了这个:

  

您无法使用$ on来收听儿童发出的事件。您必须在模板中直接使用v-on&gt;,如下例所示。

谢谢!

1 个答案:

答案 0 :(得分:1)

默认插槽中的所有内容都可通过组件内的$slots.default获得(命名插槽可通过$slots[name]获得)。因此,如果要填充父组件中的slides数组,可以检查默认插槽的内容并消除非幻灯片的节点(回车符等空格包含在节点中)。

这是一个例子。

console.clear()

Vue.component("VueSlider", {
  template: `
    <div class="slider">
       <h1>Number of slides: {{slides.length}}</h1>
        <ol>
            <li v-for="(slide,index) in slides">{{slide.name}}</li>
        </ol>
        <slot></slot>
    </div>
  `,
  data: function() {
    return {
      slides: [],
    }
  },
  mounted(){
    for (let node of this.$slots.default){
      // filter out whitespace nodes
      if (node.tag){ 
        // may want to check to add only VueSlide nodes
        this.slides.push(node.componentInstance)
      }
    }
  }
})

Vue.component("VueSlide", {
  template: `
    <div class="slide">
        <slot></slot>
    </div>
  `,
  props: {
    'name': String
  }
})

new Vue({
  el: "#app"
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
  <vue-slider>
    <vue-slide name="First slide!">First slide content</vue-slide>
    <vue-slide name="Second slide!">Second slide content</vue-slide>
  </vue-slider>
</div>

您需要检查node对象,以便查看属性。在这种情况下,我将componentInstance推送到幻灯片数组中,因为这是当前组件实例的数据属性所在的位置(因此您可以在父级中使用{{slide.name}}。但是,我通常会将自定义对象推送到只有我想要的信息的集合中。就像这样:

this.slides.push({name: node.componentInstance.name})