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 相关文章推荐
基于jquery &amp; json的省市区联动代码
Jun 26 Javascript
jquery 滚动条事件简单实例
Jul 12 Javascript
JavaScript数组合并的多种方法
May 22 Javascript
JS获取地址栏参数的两种方法(简单实用)
Jun 14 Javascript
简单的js表格操作
Sep 24 Javascript
JavaScript实现事件的中断传播和行为阻止方法示例
Jan 20 Javascript
详解HTML5 使用video标签实现选择摄像头功能
Oct 25 Javascript
vue组件中iview的modal组件爬坑问题之modal的显示与否应该是使用v-show
Apr 12 Javascript
Vue文本模糊匹配功能如何实现
Jul 30 Javascript
Jquery 获取相同NAME 或者id删除行操作
Aug 24 jQuery
JSONObject与JSONArray使用方法解析
Sep 28 Javascript
解决vue项目中出现Invalid Host header的问题
Nov 17 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
DOTA2 无惧惊涛骇浪 昆卡大型水友攻略
2020/04/20 DOTA
PHP获取搜索引擎关键字来源的函数(支持百度和谷歌等搜索引擎)
2012/10/03 PHP
php车辆违章查询数据示例
2016/10/14 PHP
如何离线执行php任务
2017/02/21 PHP
php的命名空间与自动加载实现方法
2019/08/25 PHP
php命令行模式代码实例详解
2021/02/26 PHP
jQuery 1.0.4 - New Wave Javascript(js源文件)
2007/01/15 Javascript
JavaScript禁止页面操作的示例代码
2013/12/17 Javascript
JS+CSS简单树形菜单实现方法
2015/09/12 Javascript
JavaScript中的await/async的作用和用法
2016/10/31 Javascript
js 数据存储和DOM编程
2017/02/09 Javascript
使用ionic在首页新闻中应用到的跑马灯效果的实现方法
2017/02/13 Javascript
JavaScript数组特性与实践应用深入详解
2018/12/30 Javascript
为什么Vue3.0使用Proxy实现数据监听(defineProperty表示不背这个锅)
2019/10/14 Javascript
使用Python读写及压缩和解压缩文件的示例
2016/07/08 Python
python3编码问题汇总
2016/09/06 Python
Python实现购物车功能的方法分析
2017/11/10 Python
基于python实现KNN分类算法
2020/04/23 Python
深度辨析Python的eval()与exec()的方法
2019/03/26 Python
Django基础知识 URL路由系统详解
2019/07/18 Python
django自带调试服务器的使用详解
2019/08/29 Python
Pyinstaller加密打包应用的示例代码
2020/06/11 Python
Styleonme中文网:韩国高档人气品牌
2017/06/21 全球购物
Opodo英国旅游网站:预订廉价航班、酒店和汽车租赁
2018/07/14 全球购物
客户代表实习人员自我鉴定
2013/09/27 职场文书
高中生自我评价个人范文
2013/11/09 职场文书
四查四看剖析材料
2014/02/14 职场文书
高中军训感想800字
2014/02/23 职场文书
满月酒主持词
2014/03/27 职场文书
骨干教师考核评语
2014/12/31 职场文书
银行员工考核评语
2014/12/31 职场文书
统计员岗位职责
2015/02/11 职场文书
中学音乐课教学反思
2016/02/18 职场文书
《游戏王:大师决斗》将推出新卡牌包4月4日上线
2022/03/31 其他游戏
游戏《东方异文石:爱亚利亚黎明》正式版发布
2022/04/03 其他游戏
选购到合适的激光打印机
2022/04/21 数码科技