闽公网安备 35020302035485号
// 父组件 parent.vue 的实现
<template>
<div class="parent">
<son>
<p>我是默认插槽</p>
<template #slot01>
<h4>我是具名插槽 slot01</h4>
</template>
<template #slot02="{ msg }">
<p>我是作用域插槽 slot02: {{ msg }}</p>
</template>
</son>
</div>
</template>
<script>
import son from './son';
export default {
components: {
son
}
}
</script>
// 子组件 son.vue 的实现
<template>
<div class="son">
<!-- 默认插槽 -->
<slot></slot>
<!-- 具名插槽01 -->
<slot name="slot01"></slot>
<!-- 作用域插槽 -->
<slot name="slot02" msg="hello world"></slot>
</div>
</template>
<script>
export default {
}
</script>
二. 理解插槽<!-- 默认插槽 --> <slot></slot> <!-- 具名插槽01 --> <slot name="slot01"></slot> <!-- 作用域插槽 --> <slot name="slot02" msg="hello world"></slot>如上所示,其实本质是我们在子组件中定义的slot标签会传入一个对象。对象的的属性名称和插槽的名称是关联的,同时属性值是一个函数, 函数的参数关联的是插槽中的传参。如下所示:
{
default: funtion() {},
slot01: function() {},
slot02: function({msg}) {}
}
实际上上面的对象的属性值返回的函数是一个虚拟节点,虚拟节点占位之后拿到插槽数据然后渲染出来,即我们看到的页面响应结果。我们其实可以动态生成一个子组件,通过在子组件中添加上面的对象的方法来实现一个插槽的效果。
// 父组件中引入 new-son.vue
<template>
<div class="parent">
<son>
<p>我是默认插槽</p>
<template #slot01>
<h4>我是具名插槽 slot01</h4>
</template>
<template #slot02="{ msg }">
<p>我是作用域插槽 slot02: {{ msg }}</p>
</template>
</son>
</div>
</template>
<script>
import son from './new-son';
export default {
components: {
son
}
}
</script>
// 通过动态生成虚拟节点的方式,生成组件 new-son.vue
<script>
import { h } from 'vue';
export default {
setup(props, context) {
console.log('context', context);
return () => {
return h("div", null, 'hello world')
}
}
}
</script>
// context 日志信息:
{
attrs: Object
emit: ƒ ()
expose: ƒ (exposed)
listeners: (...)
slots: {
default: ƒ ()
slot01: ƒ ()
slot02: ƒ ()
}
}
如上所示,我们通过render函数生成一个虚拟dom,然后引入到父组件中,浏览器可以看到setup的参数 context的日志信息。日志信息中的slots对象中拿到三个属性,说明我们已经拿到了插槽内容数据,但是还需要渲染出来。<script>
import { h } from 'vue';
export default {
setup(props, context) {
console.log('context', context);
const { slots } = context || {};
const _default = slots.default();
const _slot01 = slots.slot01();
const _slot02 = slots.slot02({ msg: 'hello world' });
return () => {
return h("div", null, [
..._default,
..._slot01,
..._slot02
])
}
}
}
</script>
四. 总结