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 相关文章推荐
学习YUI.Ext第七日-View&amp;JSONView Part Two-一个画室网站的案例
Mar 10 Javascript
js 提交和设置表单的值
Dec 19 Javascript
json-lib出现There is a cycle in the hierarchy解决办法
Feb 24 Javascript
仿jQuery的siblings效果的js代码
Aug 09 Javascript
Javascript中的delete操作符详细介绍
Jun 06 Javascript
两种方法解决javascript url post 特殊字符转义 + &amp; #
Apr 13 Javascript
在Javascript操作JSON对象,增加 删除 修改的简单实现
Jun 02 Javascript
tab栏切换原理
Mar 22 Javascript
js中toString()和String()区别详解
Mar 23 Javascript
微信小程序云开发实现增删改查功能
May 17 Javascript
vue-cli3中vue.config.js配置教程详解
May 29 Javascript
vue实现表格过滤功能
Sep 27 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最常用的ini函数分析 针对PHP.ini配置文件
2010/04/22 PHP
一个经典实用的PHP图像处理类分享
2014/11/18 PHP
PHP排序算法类实例
2015/06/17 PHP
Laravel使用Caching缓存数据减轻数据库查询压力的方法
2016/03/15 PHP
图文详解phpstorm配置Xdebug进行调试PHP教程
2016/06/13 PHP
PHP进程通信基础之信号
2017/02/19 PHP
javascript与webservice的通信实现代码
2010/12/25 Javascript
js获取指定的cookie的具体实现
2014/02/20 Javascript
javascript操作excel生成报表全攻略
2014/05/04 Javascript
JavaScript中使用Object.prototype.toString判断是否为数组
2015/04/01 Javascript
ANGULARJS中使用JQUERY分页控件
2015/09/16 Javascript
jQuery实现圣诞节礼物传送(花式轮播)
2016/12/25 Javascript
JavaScript组件开发之输入框加候选框
2017/03/10 Javascript
微信小程序开发之数据存储 参数传递 数据缓存
2017/04/13 Javascript
Vue.js组件间的循环引用方法示例
2017/12/27 Javascript
JS实现公告上线滚动效果
2021/01/10 Javascript
Python 字典dict使用介绍
2014/11/30 Python
python实用代码片段收集贴
2015/06/03 Python
深入理解python中的闭包和装饰器
2016/06/12 Python
Python 常用 PEP8 编码规范详解
2017/01/22 Python
Python爬取附近餐馆信息代码示例
2017/12/09 Python
浅谈python 中的 type(), dtype(), astype()的区别
2020/04/09 Python
总结python 三种常见的内存泄漏场景
2020/11/20 Python
HTML5拖放效果的实现代码
2016/11/17 HTML / CSS
英国评分最高的女性剃须刀订阅盒:FFS Beauty
2018/01/25 全球购物
Spartoo瑞典:鞋子、包包和衣服
2018/09/15 全球购物
Speedo速比涛德国官方网站:世界领先的泳装品牌
2019/08/26 全球购物
网络工程师个人的自我评价范文
2013/10/01 职场文书
教师的实习鉴定
2013/12/15 职场文书
2014年机关植树节活动方案
2014/02/27 职场文书
婚纱摄影师求职信范文
2014/04/17 职场文书
企业管理标语
2014/06/10 职场文书
小学综合实践活动总结
2014/07/07 职场文书
求职信的正确写法
2014/07/10 职场文书
2014年保育员工作总结
2014/12/02 职场文书
2015入党自传书范文
2015/06/26 职场文书