从插槽中的内容向父级发送事件

2022-01-25 00:00:00 vue.js vue-component vuejs2

I'm trying to build a flexible carousel control that allows inner content elements to force changing a slide, aswell as the carousel controls itself to change slides

A sample structure in my page looks like

<my-carousel>
  <div class="slide">
    <button @click="$emit('next')">Next</button>
  </div>

  <div class="slide">
    <button @click="$emit('close')">Close</button>
  </div>
</my-carousel>

The template for my carousel is like

<div class="carousel">
  <div class="slides" ref="slides">
    <slot></slot>
  </div> 
  <footer>
   <!-- other carousel controls like arrows, indicators etc go here -->
  </footer>
</div>

And script like

...
created() {
 this.$on('next', this.next)
}
...

Accessing the slides etc is no problem, however using $emit will not work and I can't seem to find a simple solution for this problem.

I want to component to be easily reusable without having to use

  • central event bus
  • hardcoded slides within a carousel
  • implement the next slide methods on page level and pass the current index to the control (as I'd have to do this every time I use the carousel)

解决方案

Slots are compiled against the parent component scope, therefore events you emit from the slot will only be received by the component the template belongs to.

If you want interaction between the carousel and slides, you can use a scoped slot instead which allows you to expose data and methods from the carousel to the slot.

Assuming your carousel component has next and close methods:

Carousel template:

<div class="carousel">
  <div class="slides" ref="slides">
    <slot :next="next" :close="close"></slot>
  </div> 
  <footer>
    <!-- Other carousel controls like arrows, indicators etc go here -->
  </footer>
</div>

Carousel example usage:

<my-carousel v-slot="scope">
  <div class="slide">
    <button @click="scope.next">Next</button>
  </div>

  <div class="slide">
    <button @click="scope.close">Close</button>
  </div>
</my-carousel>

相关文章