vue插槽的本质

插槽本质就是函数

父组件内通过<Child></Child> 方式是实例化子组件时如果使用了插槽,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- App.vue内 -->
<Child>
<p>默认插槽1</p>
<p>默认插槽2</p>

<template #namedSlot>
<p>具名插槽</p>
</template>

<template #scopeSlot="{ data }">
<p>{{ data }}</p>
</template>
</Child>

则插槽内容是一个对象,对象里面包含了 default namedSlot scopeSlot 这三个函数

1
2
3
4
<!-- Child.vue内 -->
<slot></slot>
<slot name="namedSlot"/>
<slot name="scopeSlot" :data="{abc: 123}"/>

<slot></slot>其实是调用那三个函数

scopeSlot( {data: {...}} ) 作用域插槽就是传了参数的函数而已

总结

  1. 父组件会把若干函数传递给子组件
  2. 子组件拿到函数并调用,返回VNode数组
  3. 子组件把VNode数组挂载到对应的<slot></slot>的位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import {h} from 'vue'
export default {
setup(props, {slots}) {
//对象里有三个函数,函数名是插槽名,参数是作用域插槽的参数
const defaultVNodeList = slots.default && slots.default()
const namedVNodeList = slots.namedSlot && slots.namedSlot()
const scopeVNodeList = slots.scopeSlot && slots.scopeSlot({data: {name:'scopeSlot'}})


return () => {
return h('div',null,[...defaultVNodeList, ...namedVNodeList, ...scopeVNodeList])
}
}
}