Skip to content

插槽

作者:Yuan Tang
更新于:5 个月前
字数统计:560 字
阅读时长:2 分钟

使用

子组件 Child.vue

vue
<template>
  <div>Child</div>
  <slot />
</template>

父组件:

vue
<script setup>
import Child from './Child.vue'
</script>

<template>
  <div>Parent</div>
  <Child>124</Child>
</template>

渲染作用域

插槽作用域取决于组件在哪里定义,作用域就在哪里。与组件最终放置渲染地方无关。

子组件 Child.vue

vue
<script setup>
import { ref } from 'vue'

const text = ref('子组件')

function show() {
  console.log(text.value)
}
</script>

<template>
  <div @click="show">
    <slot />
  </div>
</template>

父组件:

vue
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'

const text = ref('父组件')

function show() {
  console.log(text.value)
}
</script>

<template>
  <Child>
    <div @click="show">
      click
    </div>
  </Child>
</template>

最终触发点击事件的是父组件的 show 函数方法与变量。

默认值

子组件 Child.vue

vue
<script setup>
</script>

<template>
  <div>
    <slot>默认值</slot>
  </div>
</template>

父组件:

vue
<script setup>
import Child from './Child.vue'
</script>

<template>
  <Child>
    <div>click</div>
  </Child>
</template>

此时父组件传了一个内容为 click 的盒子,子组件接收页面渲染为 click ,如果父组件不传,则默认渲染“默认值”。

具名插槽

要为具名插槽传入内容,我们需要使用一个含 v-slot 指令的 <template> 元素,并将目标插槽的名字传给该指令:

子组件 Child.vue

vue
<script setup>
</script>

<template>
  <div>
    <slot name="top" />
    <slot name="middle" />
    <slot name="bottom" />
  </div>
</template>

父组件:

vue
<script setup>
import Child from './Child.vue'
</script>

<template>
  <Child>
    <template #top>
      top
    </template>
    <template #middle>
      middle
    </template>
    <template #bottom>
      bottom
    </template>
  </Child>
</template>

总结:

  1. 如果不起名,插槽默认名称为 default ,父组件不使用具名插槽的内容都会在这里渲染。
  2. 具名插槽的使用:v-slot:插槽名称 (简写形式:#插槽名称 )。

动态插槽名

插槽名称也是可以动态设置的,设置的方式与类名相同,同样也受相同的语法限制。

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

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

插槽传递数据

子组件 Child.vue

vue
<script setup>
</script>

<template>
  <div>
    <slot id="1" title="tydumpling" content="内容" />
  </div>
</template>

父组件:

vue
<script setup>
import Child from './Child.vue'
</script>

<template>
  <Child>
    <!-- 全部获取 -->
    <template #default="record">
      {{ record }} // {id: 1, title: tydumpling, content: 内容}
    </template>
    <!-- 单独获取 -->
    <template #default="{ id }">
      {{ id }} // 1
    </template>
  </Child>
</template>

简写默认插槽

vue
<script setup>
import Child from './Child.vue'
</script>

<template>
  <Child v-slot="record">
    {{ record }}
  </Child>
</template>

此时无法再使用其他插槽,无效果且会报错。

Contributors

Yuan Tang