Vue内容分发slot
前面的话
为了让组件可以组合,需要一种方式来混合父组件的内容与子组件自己的模板。这个过程被称为 内容分发 (或 “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>被丢弃

内联模板
如果子组件有 inline-template
特性,组件将把它的内容当作它的模板,而忽略真实的模板内容
但是 inline-template
让模板的作用域难以理解
var childNode = {
template: `
<div class="child">
<p>子组件</p>
</div>
`,
};
var parentNode = {
template: `
<div class="parent">
<p>父组件</p>
<child inline-template>
<p>测试内容</p>
</child>
</div>
`,
components: {
'child': childNode
},
};

匿名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
},
};

如果出现多于1个的匿名slot,vue将报错
var childNode = {
template: `
<div class="child">
<p>子组件</p>
<slot></slot>
<slot></slot>
</div>
`,
};

【默认值】
最初在 <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
},
};

当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
},
};

具名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
},
};

仍然可以有一个匿名 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">被丢弃

如果没有默认的 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">都被抛弃

作用域插槽
作用域插槽是一种特殊类型的插槽,用作使用一个 (能够传递数据到) 可重用模板替换已渲染元素。
在子组件中,只需将数据传递到插槽,就像将 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
},
};
如果渲染以上结果,得到的输出是

【列表组件】
作用域插槽更具代表性的用例是列表组件,允许组件自定义应该如何渲染列表每一项
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
1.概述 内容分发:混合父组件的内容与子组件自己的模板. 2.单个插槽 当子组件模板只有一个没有属性的插槽时,父组件传入的整个内容片段将插入到插槽所在的 DOM 位置,并替换掉插槽标签本身. 最初在 ...
- Vue一个案例引发「内容分发slot」的最全总结
今天我们继续来说说 Vue,目前一直在自学 Vue 然后也开始做一个项目实战,我一直认为在实战中去发现问题然后解决问题的学习方式是最好的,所以我在学习一些 Vue 的理论之后,就开始自己利用业余时间做 ...
- 044——VUE中组件之使用内容分发slot构建bootstrap面板panel
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 玩转vue的slot内容分发
vue的内容分发非常适合"固定部分+动态部分"的组件的场景,固定部分可以是结构固定,也可以是逻辑固定,比如下拉loading,下拉loading只是中间内容是动态的,而拉到底部都会 ...
- Vue slot插槽内容分发
slot插槽使用 使用场景,一般父组件中又一大段模板内容需要运用到子组件上.或者更加复杂的,子组件需要运用到父组件大段模板内容,而子组件却不知道挂载的内容是什么.挂载点的内容是由父组件来决定的. Sl ...
- Vue中slot内容分发
<slot>元素是一个内容分发API,使用多个内容插槽时可指定name属性 <!DOCTYPE html> <html> <head> <meta ...
- vue slot内容分发
当需要让组件组合使用,混合父组件的内容和子组件的模板的时候,就会用到slot.这个过程就叫内容分发. 最为常用的是两种slot:一种是匿名slot, 一种是具名slot. 匿名 很好理解: 就是默认, ...
- vue.js之数据传递和数据分发slot
一.组件间的数据传递 1.父组件获取子组件的数据 *子组件把自己的数据,发送到父级 *vm.$emit(事件名,数据); *v-on: @ 示例用法:当点击send按钮的时候,"111&qu ...
- slot内容分发
vue实现了一套内容分发的API,这套API基于当前的web components规范草案,将<slot>元素作为承载分发内容的出口. 在前面的父子组件中,我们提到过,在vue中,组件实例 ...
随机推荐
- MyBatis源码解析【4】反射和动态代理
通过之前的介绍,我们了解了几个组件的生命周期. 它也是我们重要装备之一. 今天我们需要搞一件更加强的装备,叫做反射和动态代理. 如果没有这件装备的话,显然后面的源码boss是打不动的. 顺便说一下,下 ...
- 简单来说一下ui-route
UI-Router被认为是AngularUI为开发者提供的最实用的一个模块,它是一个让开发者能够根据URL状态或者说是'机器状态'来组织和控制界面UI的渲染,而不是仅仅只改变路由(传统AngularJ ...
- Linux常见命令语句
查看当前目录: pwd 查看文件具体大小: ls -l 返回上一级: cd.. 返回根目录: cd / 创建一个隐藏文件 vim .test 显示隐藏文件:ls -a 编辑文件: 1.vim 文件名 ...
- 如何共享数据?- 每天5分钟玩转 Docker 容器技术(41)
数据共享是 volume 的关键特性,本节我们详细讨论通过 volume 如何在容器与 host 之间,容器与容器之间共享数据. 容器与 host 共享数据 我们有两种类型的 data volume, ...
- firefox插件开发及源码下载
在个别情况下,由于数据量巨大,造成显示性能的明显下降,此时使用c++开发firefox插件,可以提高用户使用体验. test.html: 在插件中,我们导出3个函数给js:AddStr, Pause, ...
- 2、微信小程序之弹幕的实现(无后台)
对弹幕功能主要利用环信来实现的,读者也许对环信这个东西很陌生,请先自行了解这环信再来看这文章. 环信开发文档:http://docs.easemob.com/im/400webimintegratio ...
- salesforce零基础学习(七十五)浅谈SOSL(Salesforce Object Search Language)
在工作中,我们更多操作的是一个表的对象,所以我们对SOQL的使用很多.但是有时候,我们需要对几个表进行查询操作,类似salesforce的全局搜索功能,这时,使用SOQL没法满足功能了,我们就需要使用 ...
- mongodb3 ubuntu离线安装(非apt-get)及用户管理
目前mongodb已经出到3.x,相对于2.x改动较大,本着学新不学旧的原则来捣鼓nosql数据库.最初想着apt-get安装但是软件源上都是2.x的,遂下载好后传到服务器安装. 1.下载 不得不说国 ...
- (转)VmWare下安装CentOS7图文安装教程
场景:克服安装Linux的恐惧,想装就装.在一篇博客中看到的,很有借鉴意义 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源 ...
- app耗电优化之四 使用AlarmManager对任务进行合理安排
AlarmManager 是用来设定定时任务.即用来设定那个任务在什么时候开始执行.为什么和省电有关系?这个需要和AlarmManager的使用先说起.AlarmManager 实际上只起到一个定时发 ...