MyComponent组件模板:
1 2 3 4 5 6 7
| <template> <header><slot name="header"></slot></header> <div> <slot name="body"></slot> </div> <footer><slot name="footer"></slot></footer> </template>
|
当在父组件中使用组件时,可以根据插槽名字插入自定义的内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <MyComponent> <template #header> <h1> 我是标题 </h1> </template> <template #body> <section> 我是内容 </section> </template> <template #footer> <p> 我是注脚 </p> </template> </MyComponent>
|
父组件模板会被编译成如下渲染函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function render(){ return{ type: MyComponent, children: { header() { return {type:'h1',children:'我是标题'} }, body() { return {type:'section',children:'我是内容'} }, foote() { return {type:'p',children:'我是注脚'} } } } }
|
组件模板中的插槽内容会被编译为插槽函数,而插槽函数的返回值就是具体的插槽内容
MyComponent的模板会被编译成如下渲染函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function render() { return [ { type: "header", children: [this.$slots.header()] }, { type: 'div', children: [this.$slots.body()] }, { type: 'footer', children: [this.$slots.footer()] } ] }
|
渲染插槽内容的过程,就是调用插槽函数并渲染由其返回的内容的过程,在运行时实现上,插槽依赖于setupContext中的slots对象,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| function mountComponent(vnode,container,anchor) { const slots = vnode.children || {} const setupContext = {attrs,emit,slots} const instance = { state, props: shallowReactive(props), isMounnted:false, subTree:null, slots } const renderContext = new Proxy(instance,{ get(t,k,t){ const {state,props,slots} = t if(k === '$slots')return slots }, set(t,k,v,r){ } }) }
|