vue3中插槽的使用

插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签,父组件填充的内容称为插槽内容

  • 子组件不提供插槽时,父组件填充失效
  • 父组件无填充时,<slot></slot>中的备用内容会启用生效
  • 父级模板里的所有内容都是在父级作用域中编译的,子模板里的所有内容都是在子作用域中编译的,互不影响

匿名插槽

又名默认插槽

<!-- my-button子组件定义 -->
<template>
    <button>
        <slot>SUBMIT BTN</slot>
    </button>
</template>

<!-- 父组件调用my-button -->
<my-button>
	提交按钮
</my-button>

<!-- 父组件页面渲染为 -->
<button>
    提交按钮
</button>

具名插槽

当有多个插槽时,插槽增加了name属性来正确渲染对应的部分,父组件需要使用<template></template>。可以认为匿名插槽是特殊的具名插槽

<!-- my-layout子组件定义 -->
<template>
    <div>
        <header>
            <slot name="header"></slot>
        </header>
        <main>
            <!-- 其实就是<slot name="default"></slot> -->
            <slot></slot>
        </main>
        <footer>
            <slot name="footer"></slot>
        </footer>
    </div>
</template>

<!-- 父组件调用my-layout -->
<my-layout>
    <!-- 填充内容顺序无关 -->
    <template v-slot:footer>
    	<p>我来组成脚丫子</p>
  	</template>
    
    <!-- v-slot:header可以简写为#header -->
	<template v-slot:header>
    	<h1>我来组成头部</h1>
  	</template>

    <!-- v-slot:default可以忽略不写 -->
  	<template v-slot:default>
        <p>我来组成身体</p>
  	</template>
</my-layout>

<!-- 父组件页面渲染为 -->
<div>
    <header>
        <h1>我来组成头部</h1>
    </header>
    <main>
    	<p>我来组成身体</p>
    </main>
    <footer>
        <p>我来组成脚丫子</p>
    </footer>
</div>

作用域插槽

让父级插槽内容能够访问子组件数据,数据从子组件往父组件流动。子组件通过插槽prop(任意个数)来绑定数据,父组件通过带值(命名随意)的v-slot来获取子组件的数据。

<!-- todo-list子组件定义 -->
app.component('todo-list', {
  data() {
    return {
      items: [
        { "thing1":"阅读", "thing2":"看电视" },
        { "thing1":"背单词", "thing2":"玩游戏" }
      ]
    }
  },
  template: `
    <ul>
        <li v-for="(item, index) in items">
            <!-- data即插槽prop,绑定item,index也是插槽prop,绑定index,备用内容为item.thing1 -->
        	<slot :data="item" :index="index">{{ item.thing1 }}</slot>
        </li>
    </ul>
  `
})

<!-- 正常用法:父组件调用todo-list -->
<todo-list>
  <!-- 这里default就是具名插槽的用法,slotProps来接收子组件数据,命名随意 -->
  <template v-slot:default="slotProps">
    <i class="fas fa-check"></i>
    <span class="green">{{ slotProps.index }} + ' - ' + {{ slotProps.data.thing2 }}</span>
  </template>
</todo-list>

<!-- 特殊用法:只有默认插槽时,v-slot可以写在组件上 -->
<todo-list v-slot:default="slotProps">
  <template>
    <i class="fas fa-check"></i>
    <span class="green">{{ slotProps.index }} + ' - ' + {{ slotProps.data.thing2 }}</span>
  </template>
</todo-list>

<!-- 特殊用法:v-slot有解构的用法 -->
<todo-list v-slot:default="{index, data}">
  <template>
    <i class="fas fa-check"></i>
    <span class="green">{{ index }} + ' - ' + {{ data.thing2 }}</span>
  </template>
</todo-list>

<!-- 父组件页面渲染为 -->
<ul>
    <li>
        <i class="fas fa-check"></i>
        <span class="green">0 - 看电视</span>
    </li>
    <li>
        <i class="fas fa-check"></i>
    	<span class="green">1 - 玩游戏</span>
    </li>
</ul>
Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐