Skip to content

Vue插槽

  1. 作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于父组件==> 子组件
  2. 分类:默认插槽,具名插槽,作用域插槽

1. 默认插槽

vue
<template>
  <div class="hobby">
    <ul>
      <li v-for="hobby in hobbyList" :key="hobby">{{hobby}}</li>
<!--定义一个插槽(挖个坑,等着组件的使用者进行填充)-->
      <slot>我是默认值,当使用者没有传递具体结构时,我会出现</slot>
    </ul>
  </div>
</template>

<script>
export default {
  name: "Demo",
  data() {
    return {
      hobbyList: ['打游戏', '学习', '吃饭']
    }
  }
}
</script>

<style scoped>
.hobby{
  background-color: bisque;
  width: 300px;
}
</style>
vue
<template>
  <div>
    <Demo>
      <img src="https://ecp.sgcc.com.cn/ecp2.0/portal/logo.f16c4642db4bab0d3ce0.png">
    </Demo>
  </div>
</template>

<script>
// import Test from "@/components/Test.vue";
import Demo from "@/components/Demo.vue";
// import Student from "@/components/Student.vue";

export default {
  name: 'App',
  components: { Demo }
}
</script>

使用者使用<Demo>组件:需要注意的是<image>标签是在<Demo>组件渲染完毕后再填充进去的,所以需要填充的标签css样式也可以不放到Demo组件中,在父组件中写css也可以

2. 具名插槽

当有多个插槽的时候,需要将插槽命名,也就是称为具名插槽, 首先在<Demo>组件中定义:

vue
<template>
  <div class="hobby">
    <ul>
      <li v-for="hobby in hobbyList" :key="hobby">{{hobby}}</li>
<!--定义一个插槽(挖个坑,等着组件的使用者进行填充)-->
      <slot name="center">我是默认值,当使用者没有传递具体结构时,我会出现</slot>
      <slot name="footer">我是默认值,当使用者没有传递具体结构时,我会出现</slot>
    </ul>
  </div>
</template>

<script>
export default {
  name: "Demo",
  data() {
    return {
      hobbyList: ['打游戏', '学习', '吃饭']
    }
  }
}
</script>
vue
<template>
  <div>
    <Demo>
      <img slot="center" src="https://ecp.sgcc.com.cn/ecp2.0/portal/logo.f16c4642db4bab0d3ce0.png">
      <video slot="footer"
             controls
             src="https://video.pearvideo.com/mp4/adshort/20200818/cont-1689956-15334760_adpkg-ad_hd.mp4"
             style="width: 100%; height: 100%;"/>
      <!--插槽支持追加, 并且&nbsp;&nbsp;这种在slot管理之外的元素是不会渲染到子组件中去的-->
      <img slot="footer" src="https://tx-free-imgs2.acfun.cn/kimg/bs2/zt-image-host/ChgwOGZkODdhZWNiMDQxMGYyOWVhYWM2MDcQmMzXLw.png">
      <!-- 第二种写法, template也支持slot写法还支持v-slot写法, v-slot后面不接:="xxx"     -->
      <template v-slot:footer>
        <div>多个插入的内容1</div>
        <div>多个插入的内容2</div>
      </template>
    </Demo>
  </div>
</template>

<script>
// import Test from "@/components/Test.vue";
import Demo from "@/components/Demo.vue";
// import Student from "@/components/Student.vue";

export default {
  name: 'App',
  components: {  Demo }
}
</script>

在Vue中支持插槽配合<template>标签使用,好处是自动会脱去,<template>不会渲染到组件中, 另外可以使用最新的v-slot写法,

3. 作用域插槽

  1. 理解: 数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。
vue
<template>
  <div class="hobby">
    <ul>
      <slot :hobbyListScope="hobbyList">我是默认值,当使用者没有传递具体结构时,我会出现</slot>
    </ul>
  </div>
</template>

<script>
export default {
  name: "Demo",
  data() {
    return {
      hobbyList: ['打游戏', '学习', '吃饭']
    }
  }
}
</script>
vue
<template>
  <div>
    <Demo>
      <img slot="center" src="https://ecp.sgcc.com.cn/ecp2.0/portal/logo.f16c4642db4bab0d3ce0.png">
      <!-- 第一种方式     -->
      <!--<template slot-scope="hobbyListScope">-->
      <!--<li v-for="hobby in hobbyListScope.hobbyList" :key="hobby">{{hobby}}</li>-->
      <!--</template>-->
      <!--第二种方式 通过对象解构,比如下面直接使用hobbyList      -->
      <template slot-scope="{hobbyList}">
        <li v-for="hobby in hobbyList" :key="hobby">{{ hobby }}</li>
      </template>
    </Demo>
  </div>
</template>

<script>
import Demo from "@/components/Demo.vue";

export default {
  name: 'App',
  components: {
    Demo,
  }
}
</script>