【Vue3】插槽slot

Vue3 插槽

父组件向子组件提前挖好的坑(slot)处,填入对应的内容就叫插槽。插入的内容不局限于文本,甚至可以传入多个元素和数组。


一、理解插槽

如何使用插槽

插槽使用的最多的地方就是使用ui组件库时

官网上的例子很好,用js的函数来类比。

// 父元素传入插槽内容
FancyButton('Click me!')

// FancyButton 在自己的模板中渲染插槽内容
function FancyButton(slotContent) {
  return `<button class="fancy-btn">
      ${slotContent}
    </button>`
}

渲染作用域

父组件模板中的表达式只能访问父组件的作用域;子组件模板中的表达式只能访问子组件的作用域。这和 JavaScript 的词法作用域规则是一致的。


二、默认插槽

// 父组件
<FancyButton>
  Click me! <!-- 插槽内容 -->
</FancyButton>

// FancyButton子组件
<button class="fancy-btn">
  <slot>我是默认值</slot>  <!-- 父组件的插槽内容处缺省时,此处将会显示 -->
</button>

三、具名插槽和匿名插槽

<!-- 父组件中引入子组件container -->
<container>
    <!-- 完整写法<template v-slot:header>,使用#替换v-slot: -->
  <template #header>
    <h1>header具名插槽的内容</h1>
  </template>

    <!-- 匿名插槽的内容 -->
  <template #default>       // 这行可以去掉
    <p>默认插槽的内容1</p>
    <p>默认插槽的内容2</p>
  </template>               // 这行可以去掉

  <template #footer>
    <p>footer具名插槽的内容</p>
  </template>
</container>

<!-- 子组件container -->
<div class="container">
  <div>
    <!-- 名为header的具名插槽 -->
    <slot name="header"></slot>
  </div>
  <div>
    <!-- 匿名插槽 -->
    <slot></slot>
  </div>
  <div>
    <!-- 名为footer的具名插槽 -->
    <slot name="footer"></slot>
  </div>
</div>

四、动态插槽

<base-layout>
  <template v-slot:[dynamicSlotName]>
    ...
  </template>

  <!-- 缩写为 -->
  <template #[dynamicSlotName]>
    ...
  </template>
</base-layout>


五、作用域插槽

默认作用域插槽

由于插槽的作用域,父组件无法访问到子组件的属性,可以通过props传递值那样。不过不同的是,在子组件插槽中使用符号:向上传递。所以作用域插槽是一个反向的过程,是由子组件向父组件通信的过程。

// 父组件
<!-- 完整写法<FancyButton v-slot=""> , slotProps为定义的props名,可以任意取名  -->
<FancyButton #="slotProps">
  {{slotProps.text}} {{slotProps.num}}
</FancyButton>

// FancyButton子组件
<button class="fancy-btn">
  <slot :text="刘慈欣:单走一个6" :num=6></slot>
</button>

具名作用域插槽

为什么默认作用域插槽和具名作用域插槽要分开讲,因为使用的时候不能混起来。混导致作用域传递的props混乱

<!-- 父组件中引入子组件container -->
<container>
  <template #header="{data}">
    <h1>{{data.num}}</h1>   // 666
  </template>

    <!-- 使用作用域,默认插槽不要缩写 -->
  <template #default="{data}">
    <p>{{data.age}}</p>     // 18
  </template>

  <template #footer>
    <p>footer具名插槽的内容</p>
  </template>
</container>

<!-- 子组件container -->
<div class="container">
  <div>
    <!-- name是给具名插槽用的,不会传给父组件。 -->
    <!-- 将数据result通过slot的名为data的props传递给父组件 -->
    <slot name="header" :data="result" ></slot>
  </div>
  <div>
      <!-- 这里的data由于作用域的原因不会上面具名插槽混起来的 -->
    <slot :data="defaultResult"></slot>
  </div>
  <div>
    <slot name="footer"></slot>
  </div>
</div>

let result = ref({num:666})
let defaultResult = ref({age:18})

六、更多实战用法

请到elementplus组件中学习配合使用,例如table中表格大量的使用了插槽。在el-table组件中我们使用插槽动态的对某一列某一行改变样式改变内容。

posted @ 2022-11-05 22:56  wanglei1900  阅读(1147)  评论(0编辑  收藏  举报