咱们知道在HTML中标签能够分为闭合标签和空标签,其中大多数都是闭合标签,只有少数空标签,好比:<input/>
、`<img/>
、<base/>
、<hr/>
等。在Vue中定义的组件也能够采用两种方式来书写。html
在一个组件的<template>
中假如显示一个标题<h1>Hello World!</h1>
,当咱们在调用时,不论是采用<组件名/>
或者<组件名></组件名>
都会显示 “hello world!“,因为在闭合标签中能够包含子节点和文本,所以咱们能够这样来使用<组件名>我是内容</组件名>
,可是运行的结果,确什么也没有改变。vue
若是想要在组件传入的内容正确投射,就须要一套机制来处理,在Vue中天然就是slot(插槽)机制,在React中能够经过this.props.children
来获取,而在Angular中能够经过<ng-content></ng-content>
来放置转入的内容。git
在React中传入this.props.children
的值有三种可能:github
undefined
object
array
若是要对传入的数据进行处理,React还提供了一个工具方法React.Children
来处理this.props.children
。总的来讲React把一切处理彻底交给开发人员来,彻底透明。编程
React的这种处理方式相对来讲也更加灵活,对于Vue的做用域插槽机制也能很简单的实现。segmentfault
相对于React的彻底透明模式,Angular则在传入内容时经过属性、类(class)和标签三种模式来区分和限定内容的做用域。在组件内容使用<ng-content select="xx"></ng-content>
来做为占位,具休使用方式以下:工具
<div card-body>属性</div> <ng-content select="[card-body]"></ng-content> <div card-type="body">属性值</div> <ng-content select="[card-type=body]"></ng-content> <div card body>多个属性值组合</div> <ng-content select="[card][body]"></ng-content>
<div class=".card-body">类</div> <ng-content select=".card-body"></ng-content> <div class="card body">多个类组合</div> <ng-content select=".card.body"></ng-content>
<card-body></card-body> <ng-content select="card-body"></ng-content>
<ng-content select="header"></ng-content> <div class="body">balabala...</div> <ng-content select="footer"></ng-content>
从上面的使用方式来看Angular的插槽功能仍是很强大的。this
回归到本文的主题,在Vue 2.6.0事后引入了新语法机制将之前版本的slot
和scope-slot
使用一个属性来表示。具体原因可查看其RFC。code
在新的语法中v-slot
只容许使用在 组件 和 <template></template>
标签中,而且在只能<template>
套组件和子<template>
。htm
在组件中直接放一个<slot></slot>
标签就能够接收来自组件中的内容,若是<slot>
不为空,那么内容将做为默认值显示。
在调用时就可使用v-slot:default
在组件上或者其子节点<template>
上。
具名插槽就是把分布在页面中不一样位置的<slot>
分配一个名字来标识,以区分其功能。在使用时只须要给<slot>
添加一个name
属性便可,例如:<slot name="footer"></slot>
。在使用时把默认插槽的default
换成相应的名字便可,即:<template v-slot:footer></template>
。
在使用过程没有必要每次都重复写v-slot:
,同v-on
和v-bind
同样,v-slot
也有其缩写形式,即把参数以前的全部内容 (v-slot:
) 替换为字符 #
,即<template #footer></footer>
做用域插槽的机制就是被调用的组件把组件内部的状态经过属性暴露给当前上下文。简单点说就是它只提供数据,至于当前数据怎么展现它不关心,相似于React的Render Props机制。
因为Vue官方文档写得很清楚明白这里直接上知识点:
<current-user v-slot="{ user }"> {{ user.firstName }} </current-user>
<current-user v-slot="{ user: person }"> {{ person.firstName }} </current-user> <current-user v-slot="{ user = { firstName: 'Guest' } }"> {{ user.firstName }} </current-user>
官方提到在只有默认插槽时可使用插槽的缩写语法,将v-slot:default="slotProps"
写成v-slot="slotProps"
,可是在使用时官方也说了不能和具名插槽混用,由于它会致使做用域不明确。
下面经过一个示例来实现React中的Render Props机制。
<template> <div style="height:100%" @mousemove="handleMouseMove"> <p>The current mouse position is {{ x }}, {{ y }}</p> <slot :position="position"/> </div> </template> <script> export default { name: 'Mouse', data() { return { x: 0, y: 0 } }, computed: { position: function() { return { x: this.x, y: this.y } } }, methods: { handleMouseMove(event) { this.x = event.clientX this.y = event.clientY } } } </script>
而后在其它组件中调用
<mouse> <template v-slot:default="{position}"> <img src="http://iph.href.lu/64x64?text=图片跟随鼠标" :style="{position: 'absolute', left: position.x + 'px', top: position.y + 'px'}"/> </template> </mouse>
动态插槽欢迎经过编程动态控制当前组件的插槽名,使用方式以下:
<template v-slot:[dynamicSlotName]>...</template>
<foo v-slot="foo"> <bar v-slot="bar"> <baz v-slot="baz"> {{ foo }} {{ bar }} {{ baz }} </baz> </bar> </foo>
本文只是简单对Vue的Slot的知识点作一个简单的笔记,更多的知识点官方文档比较靠谱,文中并无提到在JSX语法下的插槽使用方式,若是想要了解请查看个人另一篇文章Vue中jsx不彻底应用指南关于插槽部分的内容。