Vue内容分发slot(全面解析)


Posted in Javascript onAugust 19, 2017

前面的话

为了让组件可以组合,需要一种方式来混合父组件的内容与子组件自己的模板。这个过程被称为 内容分发 (或 “transclusion” )。Vue实现了一个内容分发 API,参照了当前 Web 组件规范草案,使用特殊的 <slot> 元素作为原始内容的插槽。本文将详细介绍Vue内容分发slot

编译作用域

在深入内容分发 API 之前,先明确内容在哪个作用域里编译。假定模板为

<child-component>
 {{ message }}
</child-component>

message 应该绑定到父组件的数据,还是绑定到子组件的数据?答案是父组件。组件作用域简单地说是:父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。

一个常见错误是试图在父组件模板内将一个指令绑定到子组件的属性/方法:

<!-- 无效 -->
<child-component v-show="someChildProperty"></child-component>

假定someChildProperty是子组件的属性,上例不会如预期工作。父组件模板不应该知道子组件的状态

如果要绑定作用域内的指令到一个组件的根节点,应当在组件自己的模板上做:

Vue.component('child-component', {
 // 有效,因为是在正确的作用域内
 template: '<div v-show="someChildProperty">Child</div>',
 data: function () {
 return {
  someChildProperty: true
 }
 }
})

类似地,分发内容是在父作用域内编译

默认丢弃

一般地,如果子组件模板不包含<slot>插口,父组件的内容将会被丢弃

var parentNode = {
 template: `
 <div class="parent">
 <p>父组件</p>
 <child>
  <p>测试内容</p>
 </child>
 </div>
 `,
 components: {
 'child': childNode
 },
};
<div id="example">
 <parent></parent>
</div>
<script src="https://unpkg.com/vue"></script>
<script>
var childNode = {
 template: `
 <div class="child">
 <p>子组件</p>
 </div>
 `,
};
var parentNode = {
 template: `
 <div class="parent">
 <p>父组件</p>
 <child>
  <p>测试内容</p>
 </child>
 </div>
 `,
 components: {
 'child': childNode
 },
};
// 创建根实例
new Vue({
 el: '#example',
 components: {
 'parent': parentNode
 }
})
</script>

如下图所示,<child>所包含的<p>测试内容</p>被丢弃

Vue内容分发slot(全面解析)

匿名slot

当子组件模板只有一个没有属性的 slot 时,父组件整个内容片段将插入到 slot 所在的 DOM 位置,并替换掉 slot 标签本身

var childNode = {
 template: `
 <div class="child">
 <p>子组件</p>
 <slot></slot>
 </div>
 `,
};
var parentNode = {
 template: `
 <div class="parent">
 <p>父组件</p>
 <child>
  <p>测试内容</p>
 </child>
 </div>
 `,
 components: {
 'child': childNode
 },
};
Vue内容分发slot(全面解析)

如果出现多于1个的匿名slot,vue将报错

var childNode = {
 template: `
 <div class="child">
 <p>子组件</p>
 <slot></slot>
 <slot></slot>
 </div>
 `,
};
Vue内容分发slot(全面解析)

【默认值】

最初在 <slot> 标签中的任何内容都被视为备用内容,或者称为默认值。备用内容在子组件的作用域内编译,并且只有在宿主元素为空,且没有要插入的内容时才显示备用内容

当slot存在默认值,且父元素在<child>中没有要插入的内容时,显示默认值

var childNode = {
 template: `
 <div class="child">
 <p>子组件</p>
 <slot><p>我是默认值</p></slot>
 </div>
 `,
};
var parentNode = {
 template: `
 <div class="parent">
 <p>父组件</p>
 <child></child>
 </div>
 `,
 components: {
 'child': childNode
 },
};
Vue内容分发slot(全面解析)

当slot存在默认值,且父元素在<child>中存在要插入的内容时,则显示设置值

var childNode = {
 template: `
 <div class="child">
 <p>子组件</p>
 <slot><p>我是默认值</p></slot>
 </div>
 `,
};
var parentNode = {
 template: `
 <div class="parent">
 <p>父组件</p>
 <child>
  <p>我是设置值</p>
 </child>
 </div>
 `,
 components: {
 'child': childNode
 },
};
Vue内容分发slot(全面解析)

具名Slot

<slot> 元素可以用一个特殊的属性 name 来配置如何分发内容。多个 slot 可以有不同的名字。具名 slot 将匹配内容片段中有对应 slot 特性的元素

var childNode = {
 template: `
 <div class="child">
 <p>子组件</p>
 <slot name="my-header">头部默认值</slot>
 <slot name="my-body">主体默认值</slot>
 <slot name="my-footer">尾部默认值</slot>
 </div>
 `,
};
var parentNode = {
 template: `
 <div class="parent">
 <p>父组件</p>
 <child>
  <p slot="my-header">我是头部</p>
  <p slot="my-footer">我是尾部</p>
 </child>
 </div>
 `,
 components: {
 'child': childNode
 },
};
Vue内容分发slot(全面解析)

仍然可以有一个匿名 slot,它是默认 slot,作为找不到匹配的内容片段的备用插槽。匿名slot只能作为没有slot属性的元素的插槽,有slot属性的元素如果没有配置slot,则会被抛弃

var childNode = {
 template: `
 <div class="child">
 <p>子组件</p>
 <slot name="my-body">主体默认值</slot>
 <slot></slot>
 </div>
 `,
};
var parentNode = {
 template: `
 <div class="parent">
 <p>父组件</p>
 <child>
  <p slot="my-body">我是主体</p>
  <p>我是其他内容</p>
  <p slot="my-footer">我是尾部</p>
 </child>
 </div>
 `,
 components: {
 'child': childNode
 },
};

<p slot="my-body">插入<slot name="my-body">中,<p>我是其他内容</p>插入<slot>中,而<p slot="my-footer">被丢弃

Vue内容分发slot(全面解析)

如果没有默认的 slot,这些找不到匹配的内容片段也将被抛弃

var childNode = {
 template: `
 <div class="child">
 <p>子组件</p>
 <slot name="my-body">主体默认值</slot>
 </div>
 `,
};
var parentNode = {
 template: `
 <div class="parent">
 <p>父组件</p>
 <child>
  <p slot="my-body">我是主体</p>
  <p>我是其他内容</p>
  <p slot="my-footer">我是尾部</p>
 </child>
 </div>
 `,
 components: {
 'child': childNode
 },
};

<p>我是其他内容</p>和<p slot="my-footer">都被抛弃

Vue内容分发slot(全面解析)

作用域插槽

作用域插槽是一种特殊类型的插槽,用作使用一个 (能够传递数据到) 可重用模板替换已渲染元素。

在子组件中,只需将数据传递到插槽,就像将 props 传递给组件一样

<div class="child">
 <slot text="hello from child"></slot>
</div>

在父级中,具有特殊属性 scope 的 <template> 元素必须存在,表示它是作用域插槽的模板。scope 的值对应一个临时变量名,此变量接收从子组件中传递的 props 对象

var childNode = {
 template: `
 <div class="child">
 <p>子组件</p>
  <slot xxx="hello from child"></slot>
 </div>
 `,
};
var parentNode = {
 template: `
 <div class="parent">
 <p>父组件</p>
 <child>
  <template scope="props">
  <p>hello from parent</p>
  <p>{{ props.xxx }}</p>
  </template>
 </child>
 </div>
 `,
 components: {
 'child': childNode
 },
};

如果渲染以上结果,得到的输出是

Vue内容分发slot(全面解析)

【列表组件】

作用域插槽更具代表性的用例是列表组件,允许组件自定义应该如何渲染列表每一项

var childNode = {
 template: `
 <ul>
 <slot name="item" v-for="item in items" :text="item.text">默认值</slot>
 </ul>
 `,
 data(){
 return{
  items:[
  {id:1,text:'第1段'},
  {id:2,text:'第2段'},
  {id:3,text:'第3段'},
  ]
 }
 }
};
var parentNode = {
 template: `
 <div class="parent">
 <p>父组件</p>
 <child>
  <template slot="item" scope="props">
  <li>{{ props.text }}</li>
  </template>
 </child>
 </div>
 `,
 components: {
 'child': childNode
 },
};
Vue内容分发slot(全面解析)

以上这篇Vue内容分发slot(全面解析)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js比较和逻辑运算符的介绍
Mar 10 Javascript
javascript刷新父页面的各种方法汇总
Sep 03 Javascript
jQuery bt气泡实现悬停显示及移开隐藏功能的方法
Jul 12 Javascript
微信小程序 教程之小程序配置
Oct 17 Javascript
详解JavaScript的闭包、IIFE、apply、函数与对象
Dec 21 Javascript
react-router 路由切换动画的实现示例
Dec 03 Javascript
微信小程序中如何使用flyio封装网络请求
Jul 03 Javascript
Bootstrap实现省市区三级联动(亲测可用)
Jul 26 Javascript
Layui选项卡制作历史浏览记录的方法
Sep 28 Javascript
webpack HappyPack实战详解
Oct 08 Javascript
使用vuex存储用户信息到localStorage的实例
Nov 11 Javascript
Angular6项目打包优化的实现方法
Dec 15 Javascript
简单的网页广告特效实例
Aug 19 #Javascript
JavaScript 完成注册页面表单校验的实例
Aug 19 #Javascript
JS模拟超市简易收银台小程序代码解析
Aug 18 #Javascript
详解JS数组Reduce()方法详解及高级技巧
Aug 18 #Javascript
javascript将url解析为json格式的两种方法
Aug 18 #Javascript
Vue组件选项props实例详解
Aug 18 #Javascript
浅谈angular4 ng-content 中隐藏的内容
Aug 18 #Javascript
You might like
神族 Protoss 剧情介绍
2020/03/14 星际争霸
不用GD库生成当前时间的PNG格式图象的程序
2006/10/09 PHP
php AJAX实例根据邮编自动完成地址信息
2008/11/23 PHP
PHP配合fiddler抓包抓取微信指数小程序数据的实现方法分析
2020/01/02 PHP
JavaScript 学习笔记(十三)Dom创建表格
2010/01/21 Javascript
锋利的jQuery 要点归纳(三) jQuery中的事件和动画(下:动画篇)
2010/03/24 Javascript
javascript的原生方法获取数组中的最大(最小)值
2012/12/19 Javascript
jquery的clone方法应用于textarea和select的bug修复
2014/06/26 Javascript
js同源策略详解
2015/05/21 Javascript
jQuery.prop() 使用详解
2015/07/19 Javascript
Javascript 字符串模板的简单实现
2016/02/13 Javascript
JS实现iframe编辑器光标位置插入内容的方法(兼容IE和Firefox)
2016/06/24 Javascript
使用jquery.qrcode.js生成二维码插件
2016/10/17 Javascript
移动端效果之IndexList详解
2017/10/20 Javascript
three.js加载obj模型的实例代码
2017/11/10 Javascript
vue toggle做一个点击切换class(实例讲解)
2018/03/13 Javascript
vue2.0 实现导航守卫的具体用法(路由守卫)
2018/05/17 Javascript
在pycharm中开发vue的方法步骤
2020/03/04 Javascript
Python 模拟员工信息数据库操作的实例
2017/10/23 Python
如何在sae中设置django,让sae的工作环境跟本地python环境一致
2017/11/21 Python
Python中的Socket 与 ScoketServer 通信及遇到问题解决方法
2019/04/01 Python
Pandas之排序函数sort_values()的实现
2019/07/09 Python
flask/django 动态查询表结构相同表名不同数据的Model实现方法
2019/08/29 Python
Python 安装 virturalenv 虚拟环境的教程详解
2020/02/21 Python
PyCharm+Pipenv虚拟环境开发和依赖管理的教程详解
2020/04/16 Python
俄罗斯在线购买飞机票、火车票、巴士票网站:Tutu.ru
2020/03/16 全球购物
c语言常见笔试题总结
2016/09/05 面试题
生物科学专业个人求职信范文
2013/12/07 职场文书
实现中国梦思想汇报2014
2014/09/13 职场文书
教师求职自荐信范文
2015/03/04 职场文书
公积金具结保证书
2015/05/11 职场文书
2015年小学二年级班主任工作总结
2015/05/21 职场文书
百日宴上的祝酒词
2015/08/10 职场文书
2016预备党员培训心得体会
2016/01/08 职场文书
PostgreSQL 插入INSERT、删除DELETE、更新UPDATE、事务transaction
2022/04/12 PostgreSQL
MySQL提升大量数据查询效率的优化神器
2022/07/07 MySQL