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 相关文章推荐
让ie运行js时提示允许阻止内容运行的解决方法
Oct 24 Javascript
jQuery源码分析-03构造jQuery对象-工具函数
Nov 14 Javascript
JavaScript高级程序设计 读书笔记之八 Function类及闭包
Feb 27 Javascript
jQuery动画效果-slideUp slideDown上下滑动示例代码
Aug 28 Javascript
Js+php实现异步拖拽上传文件
Jun 23 Javascript
JS基于递归算法实现1,2,3,4,5,6,7,8,9倒序放入数组中的方法
Jan 03 Javascript
JS利用正则表达式实现简单的密码强弱判断实例
Jun 16 Javascript
jQuery使用$.extend(true,object1, object2);实现深拷贝对象的方法分析
Mar 06 jQuery
vue组件化中slot的基本使用方法
May 01 Javascript
vuex实现像调用模板方法一样调用Mutations方法
Nov 06 Javascript
Webpack设置环境变量的一些误区详解
Dec 19 Javascript
使用refresh_token实现无感刷新页面
Apr 26 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中使用strpos函数实现屏蔽敏感关键字功能
2014/08/21 PHP
PHP实现的redis主从数据库状态检测功能示例
2017/07/20 PHP
PHP使用file_get_contents发送http请求功能简单示例
2018/04/29 PHP
网页里控制图片大小的相关代码
2006/06/13 Javascript
Jquery解析Json格式数据过程代码
2014/10/17 Javascript
在jQuery中处理XML数据的大致方法
2015/08/14 Javascript
js实现带圆角的多级下拉菜单效果
2015/08/28 Javascript
Jquery+Ajax+PHP+MySQL实现分类列表管理(上)
2015/10/28 Javascript
浅谈jquery设置和获得checkbox选中的问题
2016/08/19 Javascript
fullpage.js全屏滚动插件使用实例
2016/09/06 Javascript
浅谈html转义及防止javascript注入攻击的方法
2016/12/04 Javascript
node+koa2+mysql+bootstrap搭建一个前端论坛
2018/05/06 Javascript
详解angular部署到iis出现404解决方案
2018/08/14 Javascript
vue实现全匹配搜索列表内容
2019/09/26 Javascript
Vue+ElementUI table实现表格分页
2019/12/14 Javascript
jquery制作的移动端购物车效果完整示例
2020/02/24 jQuery
[02:04]2016国际邀请赛中国区预选赛VG.R晋级之路
2016/07/01 DOTA
python编写网页爬虫脚本并实现APScheduler调度
2014/07/28 Python
用PyQt进行Python图形界面的程序的开发的入门指引
2015/04/14 Python
python正则表达式之作业计算器
2016/03/18 Python
python的Crypto模块实现AES加密实例代码
2018/01/22 Python
python jieba分词并统计词频后输出结果到Excel和txt文档方法
2018/02/11 Python
python使用opencv按一定间隔截取视频帧
2018/03/06 Python
python中virtualenvwrapper安装与使用
2018/05/20 Python
解决csv.writer写入文件有多余的空行问题
2018/07/06 Python
利用anaconda保证64位和32位的python共存
2021/03/09 Python
python全局变量引用与修改过程解析
2020/01/07 Python
Python sublime安装及配置过程详解
2020/06/29 Python
学生会干部自荐信
2014/02/04 职场文书
《燕子》教学反思
2014/02/18 职场文书
优秀本科生求职推荐信
2014/02/24 职场文书
教师党的群众路线教育实践活动剖析材料
2014/10/09 职场文书
社区四风存在问题及整改措施
2014/10/26 职场文书
酒店财务总监岗位职责
2015/04/03 职场文书
2015年环境整治工作总结
2015/05/22 职场文书
mysql定时自动备份数据库的方法步骤
2021/07/07 MySQL