Vue插槽原理与用法详解

作者:deniro_li 时间:2024-05-09 10:43:09 

本文实例讲述了Vue插槽原理与用法。分享给大家供大家参考,具体如下:

1 插槽内容

Vue 实现了一套内容分发的 API,这套 API 基于当前的 Web Components 规范草案,将 <slot> 元素作为承载分发内容的出口。

它允许你像这样合成组件:


<div id="app1">
 <navigation-link url="/profile">
   Your Profile
 </navigation-link>
</div>

然后你在 <navigation-link> 的模板中可能会写为:


Vue.component('navigation-link', {
   template: `
     <a
       v-bind:href="url" rel="external nofollow"
       class="nav-link"
     >
     <slot></slot>
     </a>
   `
 });

当组件渲染的时候,这个 <slot> 元素将会被替换为“Your Profile”。

Vue插槽原理与用法详解

插槽内可以包含任何模板代码,包括 HTML:


<navigation-link url="/profile">
<!-- 添加一个 Font Awesome 图标 -->
<span class="fa fa-user"></span>
Your Profile
</navigation-link>

甚至其它的组件:


<navigation-link url="/profile">
<!-- 添加一个图标的组件 -->
<font-awesome-icon name="user"></font-awesome-icon>
Your Profile
</navigation-link>

如果 <navigation-link> 没有包含一个 <slot> 元素,则任何传入它的内容都会被抛弃。

2 具名插槽

有些时候我们需要多个插槽。例如,一个假设的 <base-layout> 组件多模板如下:


<div class="container">
<header>
 <!-- 我们希望把页头放这里 -->
</header>
<main>
 <!-- 我们希望把主要内容放这里 -->
</main>
<footer>
 <!-- 我们希望把页脚放这里 -->
</footer>
</div>

对于这样的情况,<slot> 元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽:


<div class="container">
<header>
 <slot name="header"></slot>
</header>
<main>
 <slot></slot>
</main>
<footer>
 <slot name="footer"></slot>
</footer>
</div>

在向具名插槽提供内容的时候,我们可以在一个父组件的 <template> 元素上使用 slot 特性:


<base-layout>
<template slot="header">
 <h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template slot="footer">
 <p>Here's some contact info</p>
</template>
</base-layout>

另一种 slot 特性的用法是直接用在一个普通的元素上:


<base-layout>
<h1 slot="header">Here might be a page title</h1>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<p slot="footer">Here's some contact info</p>
</base-layout>

我们还是可以保留一个未命名插槽,这个插槽是默认插槽,也就是说它会作为所有未匹配到插槽的内容的统一出口。上述两个示例渲染出来的 HTML 都将会是:


<div class="container">
<header>
 <h1>Here might be a page title</h1>
</header>
<main>
 <p>A paragraph for the main content.</p>
 <p>And another one.</p>
</main>
<footer>
 <p>Here's some contact info</p>
</footer>
</div>

3 默认插槽的内容

有的时候为插槽提供默认的内容是很有用的。例如,一个 <submit-button> 组件可能希望这个按钮的默认内容是“Submit”,但是同时允许用户覆写为“Save”、“Upload”或别的内容。

你可以在 <slot> 标签内部指定默认的内容来做到这一点。


<button type="submit">
<slot>Submit</slot>
</button>

如果父组件为这个插槽提供了内容,则默认的内容会被替换掉。

4 编译作用域

当你想在插槽内使用数据时,例如:


<navigation-link url="/profile">
Logged in as {{ user.name }}
</navigation-link>

该插槽可以访问跟这个模板的其它地方相同的实例属性 (也就是说“作用域”是相同的)。但这个插槽不能访问 <navigation-link> 的作用域。例如尝试访问 url 是不会工作的。牢记一条准则:

父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。

5 作用域插槽

2.1.0+ 新增

有的时候你希望提供的组件带有一个可从子组件获取数据的可复用的插槽。例如一个简单的 <todo-list> 组件的模板可能包含了如下代码:


Vue.component('todo-list',{
   template:`
   <ul>
     <li
       v-for="todo in todos"
       v-bind:key="todo.id">
       {{ todo.text }}
     </li>
   </ul>
   `
 });

但是在我们应用的某些部分,我们希望每个独立的待办项渲染出和 todo.text 不太一样的东西。这也是作用域插槽的用武之地。

为了让这个特性成为可能,你需要做的全部事情就是将待办项内容包裹在一个 <slot> 元素上,然后将所有和其上下文相关的数据传递给这个插槽:在这个例子中,这个数据是 todo 对象:


<ul>
<li
 v-for="todo in todos"
 v-bind:key="todo.id"
>
 <!-- 我们为每个 todo 准备了一个插槽,-->
 <!-- 将 `todo` 对象作为一个插槽的 prop 传入。-->
 <slot v-bind:todo="todo">
  <!-- 回退的内容 -->
  {{ todo.text }}
 </slot>
</li>
</ul>

现在当我们使用 <todo-list> 组件的时候,我们可以选择为待办项定义一个不一样的<template> 作为替代方案,并且可以通过 slot-scope 特性从子组件获取数据:


<todo-list v-bind:todos="todos">
 <!--插槽作用域的名字是 slotProps-->
 <template slot-scope="slotProps">
   <!-- 为指定的待办项定义一个模板-->
   <span v-if="slotProps.todo.isComplete">✓</span>
   {{ slotProps.todo.text }}
 </template>
</todo-list>

在 2.5.0+,slot-scope 不再限制在 <template> 元素上使用,而可以用在插槽内的任何元素或组件上。

解构 slot-scope

如果一个 JavaScript 表达式在一个函数定义的参数位置有效,那么这个表达式实际上就可以被 slot-scope 接受。也就是说你可以在支持的环境下 单文件组件或现代浏览器),在这些表达式中使用 ES2015 解构语法。例如:


<todo-list v-bind:todos="todos">
<template slot-scope="{ todo }">
 <span v-if="todo.isComplete">✓</span>
 {{ todo.text }}
</template>
</todo-list>

这会使作用域插槽变得更干净一些。

希望本文所述对大家vue.js程序设计有所帮助。

来源:https://blog.csdn.net/deniro_li/article/details/80690693

标签:Vue,插槽
0
投稿

猜你喜欢

  • 用Python编写个解释器实现方法接受

    2023-01-11 15:50:08
  • jQuery+AJAX实现网页无刷新上传

    2024-04-17 10:39:39
  • django将网络中的图片,保存成model中的ImageField的实例

    2023-12-23 01:11:33
  • Python实现人机中国象棋游戏

    2023-01-28 21:33:52
  • django session完成状态保持的方法

    2021-12-07 16:12:02
  • 在SQL中修改数据的基础语句

    2024-01-28 06:02:15
  • 十个实用且简单的MySQL函数

    2024-01-27 06:37:16
  • Python压缩解压缩zip文件及破解zip文件密码的方法

    2023-04-20 10:30:30
  • 在python中利用pycharm自定义代码块教程(三步搞定)

    2022-11-20 01:00:50
  • MySQL之mysqldump的使用详解

    2024-01-25 10:53:07
  • 详解MySQL数据库优化的八种方式(经典必看)

    2024-01-13 11:32:20
  • django框架两个使用模板实例

    2023-11-01 20:05:18
  • 通过索引优化含ORDER BY的MySQL语句

    2010-03-13 12:20:00
  • [翻译]标记语言和样式手册 chapter 6 短语元素

    2008-01-25 16:37:00
  • 源码编译安装MySQL8.0.20的详细教程

    2024-01-22 11:55:52
  • jquery实现点击页面计算点击次数

    2024-04-16 10:33:17
  • 纯数字不重复排列的另类方法

    2009-12-04 18:25:00
  • 安装sql server 2008 management提示已安装 SQL Server 2005 Express的解决方法

    2024-01-15 12:49:03
  • MySQL数据库常用命令小结

    2024-01-15 22:16:31
  • PyQt5 在QListWidget自定义Item的操作

    2023-07-05 16:35:49
  • asp之家 网络编程 m.aspxhome.com