简介
插槽:简单理解就是组件内部留一个或多个的插槽位置,可供组件传对应的模板代码进去。插槽的出现,让组件变的更加灵活。
一、匿名插槽
// 组件(父) <my-component> <p>hello,world!</p> </my-component> // 组件内部(子) <div class="child-page"> <h1>子页面</h1> <slot></slot> // 替换为 <p>hello,world!</p> </div> // 渲染结果 <div class="child-page"> <h1>子页面</h1> <p>hello,world!</p> </div>
以上是最简单的匿名插槽eg
二、具名插槽
顾名思义就是带名字的插槽,假如需要在组件内部预留多个插槽位置,就需要为插槽定义名字,指定插入的位置。
// 组件(父) <my-component> <template v-slot:header> <p>头部</p> </template> <template v-slot:footer> <p>脚部</p> </template> <p>身体</p> </my-component> // 组件内部(子) <div class="child-page"> <h1>子页面</h1> <slot name="header"></slot> <slot></slot> // 等价于 <slot name="default"></slot> <slot name="footer"></slot> </div> // 渲染结果 <div class="child-page"> <h1>子页面</h1> <p>头部</p> <p>身体</p> <p>脚部</p> </div>
vue >=2.6.0版本,使用v-slot替代slot 和 slot-scope。
注意三点
- 具名插槽的内容必须使用模板<template></template>包裹
- 不指定名字的模板插入匿名插槽中,推荐使用具名插槽,方便代码追踪且直观清楚
- 匿名插槽具有隐藏的名字"default"
三、具名插槽的缩写和动态插槽名
具名插槽缩写
<my-component> <template #header> <p>头部</p> </template> <template #footer> <p>脚部</p> </template> <template #body> <p>身体</p> </template> </my-component>
动态插槽名
<my-component> <template #[headerPart]> // v-slot:[headerPart] <p>头部</p> </template> <template #footer> <p>脚部</p> </template> <template #body> <p>身体</p> </template> </my-component> ... data() { return { headerPart: 'header' } }
四、插槽参数传递
父传子
// 组件(父) <my-component :title="'我是'" > <template #header> <p>头部</p> </template> <template #footer> <p>脚部</p> </template> <template #body> <p>身体</p> </template> </my-component> // 组件内部(子) <div class="child-page"> <h1>{{title}}子页面</h1> <slot name="header"></slot> <slot name="body"></slot> <slot name="footer"></slot> </div> props: { title: { type: String } }
以下这种传参是错误的
<my-component :title="'我是'" > <template #header> <p>{{title}}头部</p> // 错误 </template> <template #footer> <p>脚部</p> </template> <template #body> <p>身体</p> </template> </my-component>
所以如果需要动态修改插槽的内容,就需要子组件传参给父组件。
子传父
// 组件(父)传参并接受参数 <my-component v-bind="layout" // 传递参数 > // 可以使用ES6解构{ slotProps } <template #header="slotProps"> // 接受参数 <p>{{slotProps.headers}}</p> </template> <template #footer="slotProps"> <p>{{slotProps.footers}}</p> </template> <template #body="slotProps"> <p>{{slotProps.bodys}}</p> </template> </my-component> ... data() { return { layout: { header: '头部', body: '身体', footer: '脚部' } } } // 组件内部(子) <div class="child-page"> <h1>子页面</h1> <slot name="header" :headers="header"></slot> <slot name="body" :bodys="body"></slot> <slot name="footer" :footers="footer"></slot> </div> ... props: { header: { require: true }, body: { require: true }, footer: { require: true } }
总结:
父组件传参给子组件,props接收后,插槽slot再通过绑定属性传递参数返回给父组件,不管是模板代码还是数据,控制权完全掌握在父组件手里。