Vue3 插槽Slot

关于作用域

默认插槽、具名插槽只能访问使用者的作用域,插槽的内容无法访问子组件的数据。Vue模版中表达式只能访问其定义时所处的作用域,这和Javascript的语法作用域规则是一致的。

如果需要访问子组件中的作用域,则使用作用域插槽

默认插槽

<slot>元素是一个插槽出口(slot outlet),标示了父元素提供的插槽内容(slot conten)将在哪里被渲染。

一个小栗子,使用默认插槽展示父组件中的一个值

javascript 复制代码
<template>
  <div class="box">
    <div>子组件中的展示父组件的插槽如下:</div>
    <slot></slot>
  </div>
</template>
<style scoped>
.box {
  display: flex;
  flex-direction: column;
  margin: 15px;
  padding: 10px;
  background-color: antiquewhite;
}
</style>
javascript 复制代码
<template>
  <div class="box">
    <A>
      <div style="padding: 10px;">父组件中使用A子组件的默认插槽,显示父组件中的值:{{ defaultVal }}</div>
    </A>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import A from './component/index.vue'

// 默认插槽
const defaultVal = "A use Val";

</script>
<style scoped>
.box {
  display: flex;
  flex-direction: column;
  margin: 20px;
}
</style>
具名插槽

有时我们在同一个组件中希望使用多个插槽,此时可以使用具名插槽

一个小栗子,同一个子组件中同时使用具名插槽和默认插槽,代码如下

javascript 复制代码
<template>
  <div class="box">
    <slot name="top"></slot>
    <slot></slot>
    <slot name="down"></slot>
  </div>
</template>
<style scoped>
.box {
  display: flex;
  flex-direction: column;
  margin: 20px;
  padding: 10px;
  background-color: slategray;
}
</style>
javascript 复制代码
<template>
  <div class="box">
    <B>
      <top>
        <div>父组件中使用子组件B中的具名插槽top,显示父组件中的值:{{ topVal }}</div>
      </top>
      <div>
import { skeletonItemProps } from 'element-plus';
import { sliderButtonProps } from 'element-plus/es/components/slider/src/button';
        <div>父组件中使用子组件B中的默认插槽,显示父组件中的值:{{ bDefault }}</div>
      </div>
      <down>
        <div>父组件中使用子组件B中的具名插槽down,显示父组件中的值:{{ downVal }}</div>
      </down>
    </B>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import B from './component/b.vue'


// 具名插槽与默认插槽一起使用
const topVal = "B use top";
const bDefault = "B default val";
const downVal = "B use down";

</script>
<style scoped>
.box {
  display: flex;
  flex-direction: column;
  margin: 20px;
}
</style>
作用域插槽

某些场景下插槽的内容可能想要同时使用父组件域内和子组件域内的数据。要做到这一点,我们需要一种方法来让子组件在渲染时将一部分数据提供给插槽。

我们也确实有办法这么做!可以像对组件传递 props 那样,向一个插槽的出口上传递 attributes。

一个小栗子,在同一子组件中同时使用具名插槽和作用域插槽

javascript 复制代码
<template>
  <div class="box">
    <slot name="top" :aVal="aVal"></slot>
    <slot :bVal="bVal"></slot>
    <slot name="down" :cVal="cVal" :dVal="dVal"></slot>
  </div>
</template>
<script setup>
const aVal = "a val of c component";
const bVal = "b val of c component";
const cVal = "c val of c component";
const dVal = "d val of c component";
</script>
<style scoped>
.box {
  display: flex;
  flex-direction: column;
  margin: 20px;
  padding: 10px;
  background-color: cadetblue;
}
</style>
javascript 复制代码
<template>
  <div class="box">
    <C>
      <template #top="{ aVal }">
        <div>
          {{ introVal }}的具名插槽top,并显示子组件中的值:{{ aVal }}
        </div>
      </template>
      <template #default="{ bVal }">
        <div>
          {{ introVal }}的默认插槽,并显示子组件中的值:{{ bVal }}
        </div>
      </template>
      <template #down="{ cVal, dVal }">
        <div>
          {{ introVal }}的具名插槽down,并显示组件中的值:
            cVal = {{ cVal }}, 
            dVal = {{ dVal }}
        </div>
      </template>
    </C>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import C from './component/c.vue'

// 作用域插槽并同时使用具名插槽
const introVal = "父组件中使用子组件C";

</script>
<style scoped>
.box {
  display: flex;
  flex-direction: column;
  margin: 20px;
}
</style>
无渲染插槽

一些组件可能只包括了逻辑而不需要自己渲染内容,视图输出通过作用域插槽全权交给了消费者组件。我们将这种类型的组件称为无渲染组件。

一个小栗子,在子组件中声明x、y两个点,通过按钮增加它们的值,并在使用者的作用域中展示x、y最新的值。

javascript 复制代码
<template>
  <div class="box">
    <div>
      <div style="margin: 30px; padding: 45px; width: 360px; background-color: aqua;" @click="addX">add x</div>
      <div style="margin: 30px; padding: 45px; width: 360px; background-color: aqua;" @click="addY">add y</div>
    </div>
    <slot name="transVal" :x="x" :y="y"></slot>
  </div>
</template>
<script setup>
import { ref } from 'vue'
const x = ref(23); 
const y = ref(25);
const addX = () => {
  let val = x.value;
  val++;
  x.value = val;
}
const addY = () => {
  let val = y.value;
  val++;
  y.value = val;
}
</script>
<style scoped>
.box {
  display: flex;
  flex-direction: column;
  margin: 20px;
  padding: 10px;
  background-color: hotpink;
}
</style>
javascript 复制代码
<template>
  <div class="box">
    <E>
      <template #transVal="{ x, y }">
        E component x = {{ x }}, y = {{ y }}
      </template>
    </E>
  </div>
</template>
<script setup>
import E from './component/e.vue'
</script>
<style scoped>
.box {
  display: flex;
  flex-direction: column;
  margin: 20px;
}
</style>

在这个例子中子组件中使用了ref,可以看到子组件中的值发生变化时,在父组件中显示的值也有更新

相关推荐
孔令飞5 小时前
Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中
前端
可乐鸡翅yeah_5 小时前
hls.js 缓冲区参数 maxBufferLength、maxBufferSize 通俗讲解与业务调参
开发语言·javascript·ios·音视频·safari·m3u8
溪语流沙5 小时前
【Web全栈进阶】PostgreSQL上手:Docker跑库 + 把早报站从SQLite迁过去
前端·docker·postgresql
IT_陈寒5 小时前
SpringBoot自动配置的坑:你以为的捷径可能是弯路
前端·人工智能·后端
paopaokaka_luck5 小时前
高校社团管理(AI辅助任务分配、协同过滤算法推荐、ECharts数据可视化、活动参与闭环、校园交流与反馈、器材借还管理)
java·前端·javascript·spring boot·数据分析·echarts
vx_Biye_Design5 小时前
springboot小区管理系统68491-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·课程设计·express
500845 小时前
React Native for OpenHarmony 实战:三方库 react-native-volume-control 的鸿蒙化适配指南
javascript·react native·react.js·electron·harmonyos
薛一半5 小时前
React-Redux三重优化实战揭秘
javascript·vue.js·react.js
专业程序开发源5 小时前
springboot外卖系统94294-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·php·课程设计
Dovis(誓平步青云)5 小时前
导览音频切换太快,旧讲解不能覆盖新展品
android·前端·javascript·ecmascript·音视频·宠物