vue 插槽(二)

渲染作用域

插槽内容可以访问到父组件的数据作用域,因为插槽内容本身是在父组件模板中定义的。举例来说:

html 复制代码
<span>{{ message }}</span>
<FancyButton>{{ message }}</FancyButton>

这里的两个 {``{ message }} 插值表达式渲染的内容都是一样的。

插槽内容无法访问子组件的数据。Vue 模板中的表达式只能访问其定义时所处的作用域,这和 JavaScript 的词法作用域规则是一致的。换言之:

父组件模板中的表达式只能访问父组件的作用域;子组件模板中的表达式只能访问子组件的作用域。

默认内容

在外部没有提供任何内容的情况下,可以为插槽指定默认内容。比如有这样一个 <SubmitButton> 组件:

html 复制代码
<button type="submit">
  <slot></slot>
</button>
<button type="submit">
  <slot>
    Submit <!-- 默认内容 -->
  </slot>
</button>

现在,当我们在父组件中使用 <SubmitButton> 且没有提供任何插槽内容时:

html 复制代码
<SubmitButton />

"Submit"将会被作为默认内容渲染:

html 复制代码
<button type="submit">Submit</button>

但如果我们提供了插槽内容:

html 复制代码
<SubmitButton>Save</SubmitButton>

那么被显式提供的内容会取代默认内容:

html 复制代码
<button type="submit">Save</button>

具名插槽

有时在一个组件中包含多个插槽出口是很有用的。举例来说,在一个 <BaseLayout> 组件中,有如下模板:

html 复制代码
<div class="container">
  <header>
    <!-- 标题内容放这里 -->
  </header>
  <main>
    <!-- 主要内容放这里 -->
  </main>
  <footer>
    <!-- 底部内容放这里 -->
  </footer>
</div>

对于这种场景,<slot> 元素可以有一个特殊的 attribute name,用来给各个插槽分配唯一的 ID,以确定每一处要渲染的内容:

html 复制代码
<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

这类带 name 的插槽被称为具名插槽 (named slots)。没有提供 name<slot> 出口会隐式地命名为"default"。

在父组件中使用 <BaseLayout> 时,我们需要一种方式将多个插槽内容传入到各自目标插槽的出口。此时就需要用到具名插槽了:

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

html 复制代码
<BaseLayout>
  <template v-slot:header>
    <!-- header 插槽的内容放这里 -->
  </template>
</BaseLayout>

动态插槽名

动态指令参数v-slot 上也是有效的,即可以定义下面这样的动态插槽名:

html 复制代码
<base-layout>
  <template v-slot:[dynamicSlotName]>
    ...
  </template>

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

作用域插槽

在上面的渲染作用域中我们讨论到,插槽的内容无法访问到子组件的状态。

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

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

html 复制代码
<!-- <MyComponent> 的模板 -->
<div>
  <slot :text="greetingMessage" :count="1"></slot>
</div>
<MyComponent v-slot="slotProps">
  {{ slotProps.text }} {{ slotProps.count }}
</MyComponent>
相关推荐
喜欢你,还有大家23 分钟前
FTP文件传输服务
linux·运维·服务器·前端
该用户已不存在27 分钟前
你没有听说过的7个Windows开发必备工具
前端·windows·后端
Bi38 分钟前
Dokploy安装和部署项目流程
运维·前端
普通网友40 分钟前
前端安全攻防:XSS, CSRF 等防范与检测
前端·安全·xss
携欢42 分钟前
PortSwigger靶场之Reflected XSS into attribute with angle brackets HTML-encoded通关秘籍
前端·xss
小爱同学_1 小时前
React知识:useState和useRef的使用
前端·react.js
再学一点就睡1 小时前
双 Token 认证机制:从原理到实践的完整实现
前端·javascript·后端
随风飞翔的胖子1 小时前
js-cookie详细介绍及在vue3中的使用方法
vue.js·浏览器
wallflower20201 小时前
滑动窗口算法在前端开发中的探索与应用
前端·算法
蚂蚁绊大象1 小时前
flutter第二话题-布局约束
前端