vue3源码分析——实现slots( 二 )

分析通过上面测试用例,发现以下内容:

  1. renderSlot传入第二个参数,然后可以获取对于的slots
问题解决
直接在renderSlot里面传入第二个参数即可
编码// 最后还需要使用renderSlot函数export function renderSlots(slots, name = 'default') {const slot = slots[name]if (slot) {return createVNode('div', {}, slot)}}复制代码
这一步是不是比较简单,相对起前面来说,正所谓,前面考虑好了,后面就舒服,接下来实现作用域插槽
作用域插槽作用域插槽是,每个slot里面可以传入数据,数据只在当前的slot有效,具体请看测试用例
测试用例test('测试作用域插槽', () => {const Foo = {name: 'Foo',render() {return h('div', { class: 'foo' },[renderSlots(this.$slots, 'header', { children: 'foo' }),h('div', { class: 'default' }, 'default'),renderSlots(this.$slots, 'footer')]);}}const app = createApp({name: 'App',render() {return h('div', { class: 'container' }, [h(Foo, {}, {header: ({ children }) => h('h1', {}, 'header ' + children),footer: h('p', {}, 'footer')})])}})const appDoc = document.querySelector('#app')app.mount(appDoc);const container = document.querySelector('.container') as HTMLElementexpect(container.innerHTML).toBe('<div class="foo"><div><h1>header foo</h1></div><div class="default">default</div><div><p>footer</p></div></div>')})复制代码需求分析通过上面的测试用例,分析出以下内容:
  1. 传入插槽的时候,传入一个函数,函数可以拿到子组件传过来的参数
  2. renderSlots可以传入第三个参数props, 用于接收子组件往父组件传入的参数
问题解决:
  1. 问题1: 只需要在传入插槽的时候进行一下判断,如果是函数的话,需要进行函数执行,并且传入参数
  2. 问题2: 也是对传入的内容进行判断,函数做传入参数处理
编码// 在renderSlot里面传入第三个参数export function renderSlots(slots, name = 'default', props = {}) {const slot = slots[name];if (slot) {if (isFunction(slot)) {return createVNode('div', {}, slot(props))}return createVNode('div', {}, slot)}}// initSlot时候,需要进行函数判断 const slots = {}// 遍历childrenfor (const key in children) {// 判断传入的是否是函数,如果是函数的话,需要进行执行,并且传入参数if (isFunction(children[key])) {slots[key] = (props) => Array.isArray(children[key](props)) ? children[key](props) : [children[key](props)]} else {slots[key] = Array.isArray(children[key]) ? children[key] : [children[key]]}}instance.slots = slots复制代码到此,整个测试用例就可以完美通过啦!




推荐阅读