Vue插槽原理与用法详解


Posted in Javascript onMarch 05, 2019

本文实例讲述了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程序设计有所帮助。

Javascript 相关文章推荐
setInterval与clearInterval的使用示例代码
Jan 28 Javascript
JavaScript通过setTimeout实时显示当前时间的方法
Apr 16 Javascript
javascript解析xml实现省市县三级联动的方法
Jul 25 Javascript
为jQuery-easyui的tab组件添加右键菜单功能的简单实例
Oct 10 Javascript
JS计算两个时间相差分钟数的方法示例
Jan 10 Javascript
p5.js入门教程之平滑过渡(Easing)
Mar 16 Javascript
element-ui 设置菜单栏展开的方法
Aug 22 Javascript
koa socket即时通讯的示例代码
Sep 07 Javascript
使用vue实现一个电子签名组件的示例代码
Jan 06 Javascript
JS数组方法push()、pop()用法实例分析
Jan 18 Javascript
Vue循环遍历选项赋值到对应控件的实现方法
Jun 22 Javascript
JavaScript缺少insertAfter解决方案
Jul 03 Javascript
JavaScript基于遍历操作实现对象深拷贝功能示例
Mar 05 #Javascript
JavaScript函数定义方法实例详解
Mar 05 #Javascript
C#程序员入门学习微信小程序的笔记
Mar 05 #Javascript
JavaScript函数的4种调用方法实例分析
Mar 05 #Javascript
微信小程序保存多张图片的实现方法
Mar 05 #Javascript
JS添加或删除HTML dom元素的方法实例分析
Mar 05 #Javascript
迅速了解一下ES10中Object.fromEntries的用法使用
Mar 05 #Javascript
You might like
php连接mysql数据库代码
2009/03/10 PHP
php实现图片上传并进行替换操作
2016/03/15 PHP
php简单实现批量上传图片的方法
2016/05/09 PHP
javascript 硬盘序列号+其它硬件信息
2008/12/23 Javascript
jquery 1.3.2 IE8中的一点点的小问题解决方法
2009/07/10 Javascript
JavaScript 空位补零实现代码
2010/02/26 Javascript
js 蒙版进度条(结合图片)
2010/03/10 Javascript
AJAX异步从优酷专辑中采集所有视频及信息(JavaScript代码)
2010/11/20 Javascript
基于jquery的可多选的下拉列表框
2012/07/20 Javascript
关于js new Date() 出现NaN 的分析
2012/10/23 Javascript
jQuery侧边栏随窗口滚动实现方法
2013/03/04 Javascript
javasript实现密码的隐藏与显示
2015/05/08 Javascript
利用jQuery设计一个简单的web音乐播放器的实例分享
2016/03/08 Javascript
EasyUi中的Combogrid 实现分页和动态搜索远程数据
2016/04/01 Javascript
javascript作用域链与执行环境详解
2017/03/25 Javascript
NodeJS收发GET和POST请求的示例代码
2017/08/25 NodeJs
jQuery获取所有父级元素及同级元素及子元素的方法(推荐)
2018/01/21 jQuery
vue.js内置组件之keep-alive组件使用
2018/07/10 Javascript
VsCode与Node.js知识点详解
2019/09/05 Javascript
vue+elementui实现点击table中的单元格触发事件--弹框
2020/07/18 Javascript
python实现的简单猜数字游戏
2015/04/04 Python
python协程用法实例分析
2015/06/04 Python
pytorch torch.expand和torch.repeat的区别详解
2019/11/05 Python
Anaconda 查看、创建、管理和使用python环境的方法
2019/12/03 Python
python中的django是做什么的
2020/07/31 Python
Python ConfigParser模块的使用示例
2020/10/12 Python
HTML5中meta属性的使用方法
2016/02/29 HTML / CSS
数以千计的折扣工业产品:ESE Direct
2018/05/20 全球购物
大学军训感言600字
2014/02/25 职场文书
毕业留言寄语大全
2014/04/10 职场文书
小学秋季运动会报道稿
2014/09/30 职场文书
一般基层干部群众路线教育实践活动个人对照检查材料
2014/11/04 职场文书
学校社团活动总结
2015/05/07 职场文书
法人身份证明书
2015/06/18 职场文书
运动会宣传语
2015/07/13 职场文书
90行Python代码开发个人云盘应用
2021/04/20 Python