插槽
插槽的本质是一个返回VNode的函数
在vm上有以下两个属性
vm.$slots
类型:vm.$slots是一个对象,对象里面放着父组件传来的所有的具名插槽和默认插槽的数组
typescript
{
[name: string]: ?Array<VNode>
}为什么是数组
因为父组件使用使用插槽时,默认插槽和同名的具名插槽可以传递多个
vue
<template>
<Child>
<span slot="aaa">456</span>
<span slot="aaa">456</span>
<span slot="bbb">456</span>
<span slot="ccc">789</span>
<span>789</span>
<span>789</span>
</Child>
</template>vue
<script>
mounted() {
console.log(this.$slots);
},
</script>打印结果如下所示

vm.$scopedSlots
vm.$scopedSlots也是一个对象,里面存放一个个函数,这些函数的返回值是包含父组件传来的所有插槽的数组(包含默认、具名、作用域插槽)
typescript
{
[name: string]: props => Array<VNode> | undefined
}vue
<template>
<Child>
<span slot="aaa">456</span>
<span slot="aaa">456</span>
<span slot="bbb">456</span>
<span slot="ccc">789</span>
<span slot="ddd" slot-scope="data">{{ data }}</span>
<span>789</span>
<span>789</span>
</Child>
</template>vue
<script>
export default {
mounted() {
console.log(this.$scopedSlots);
},
};
</script>打印结果如下

可以看到,this.$scopedSlots接收了父组件传来的所有插槽
我们获取下这些函数的返回值
vue
<script>
export default {
mounted() {
const obj = {};
for (let key in this.$scopedSlots) {
const Vnode = this.$scopedSlots[key]();
obj[key] = Vnode;
}
console.log(obj)
},
};
</script>
不同点
vm.$slots和vm.$scopedSlots都可以获取父组件传递来的插槽,不同的是获取的是数据格式和插槽种类
数据格式:
vm.$slots里面是包含所有插槽的数组vm.$scopedSlots里面是返回值为插槽的函数
插槽种类:
vm.$slots只可以获取默认、具名插槽vm.$scopedSlots可以获取所有插槽
a-table的骚操作
效果描述
正常使用作用域插槽时,slot标签上的数据都会被放进一个对象
vue
<template>
<div>
<slot name="scoped" :num="666" idoName="ikun"></slot>
</div>
</template>vue
<Child>
<span slot="scoped" slot-scope="data">{{ data }}</span>
<!-- { "num": 666, "idoName": "ikun" } -->
</Child>也可以使用解构
vue
<Child>
<span slot="scoped" slot-scope="{num,idoName}">{{ num }},{{idoName}}</span>
</Child>但是在a-table的插槽中,却可以这样使用
vue
<a-table>
<span solt="solotName" solt-scope="value,record,index"></span>
</a-table>可以看到solt-scope="value,record,index"没有结构确可以获取三个数据
原理解析
原理则是a-table的组件源码并不是vue文件,而是使用的渲染函数
js
export default {
name: "Child",
data() {
return {
value: 666,
record: {
name: "ikun",
},
index: 0,
};
},
mounted() {},
methods: {},
render: function (h) {
const slotsNodes = [];
for (let key in this.$scopedSlots) {
const Vnode = this.$scopedSlots[key](this.value, this.record, this.index);
slotsNodes.push(Vnode);
}
return h("div", [...slotsNodes]);
},
};vue
<Child>
<span slot="scoped" slot-scope="value, record, index">
{{ value }},{{ record }},{{ index }}
</span>
</Child>效果如下

