// 父组件 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>四. 总结