插槽
slot又名插槽,vue内容分发机制,组件内部的模板引擎使用slot元素作为承载分发内容的出口
插槽slot是子组件的一个模板标签元素,而这一个元素是否显示,以及怎么显示是由父组件决定的
slot分为三类:默认插槽、具名插槽、作用域插槽
- 默认插槽
父组件代码详情
<template> <div class="parent"> <h1>这里是parent组件</h1> <Child> <h3>这是parent组件传递给child组件的值</h3> </Child> </div> </template> <script> import Child from "../component/Child.vue" </script>
子组件代码详情
<template> <div class="child"> <h1>这里是child组件</h1> <Child> <h3>这是child组件</h3> <slot></slot> </Child> </div> </template>
运行结果:
又叫匿名插槽,当插槽slot没有指定name属性值的时候一个默认显示一个插槽,一个组件内只有一个匿名插槽
- 具名插槽
带有具体名字的插槽,也就是带有name属性的slot,一个组件可以出现多个具名插槽
父组件代码详情
<template> <div class="parent"> <h1>这里是parent组件</h1> <Child> <div slot="header">给header内容</div> <div slot="main">给main内容</div> <div slot="footer">给footer内容</div> </Child> </div> </template>
子组件代码详情
<template> <div class="child"> <h1>这里是parent组件</h1> <Child> <div name="header">给header内容</div> <div name="main">给main内容</div> <div name="footer">给footer内容</div> </Child> </div> </template>
运行结果:
- 作用域插槽
在子组件渲染作用域插槽时,可以将子组件内部的数据传递给父组件,让父组件根据子组件传递过来的数据如何渲染该插槽
父组件代码详情
<template> <button @click="show">显示隐藏</button> <div class="home" v-show="isShow"> <Dialog title="商品选择"> <!-- 匿名插槽的使用 --> <!-- 写法一 --> <!-- 12243 --> <!-- 写法二 --> <template #default> <!-- 666666666666666666 --> <FruitList> <template #default="{goods}">{{ goods }}</template> </FruitList> </template> <!-- 具名插槽使用 --> <!-- 写法一 --> <!-- <template v-slot:footer> <Rbutton>取消</Rbutton> <Rbutton>确认</Rbutton> </template> --> <!-- 写法二 --> <template #footer> <Rbutton style=" display: inline-block;border-radius: 5px;margin-right: 10px;">取消</Rbutton> <Rbutton style="background-color: #1890ff; display: inline-block; border-radius: 5px;">确认</Rbutton> </template> </Dialog> </div> </template> <script> import Dialog from '@/components/Dialog.vue' import Rbutton from '@/components/Rbutton.vue'; import FruitList from '@/components/FruitList.vue'; export default { data(){ return{ isShow:false } }, name: 'DialogParent', components: { Dialog, Rbutton, FruitList }, methods:{ onAddCart(gid,gname){ console.log(gid,gname); }, show(){ this.isShow=!this.isShow } } } </script> <style lang="scss" scoped> .home{ // position: relative; background-color: yellow; } </style>
子组件代码详情
<template> <div class="fruit"> <table class="ftable"> <thead> <tr> <td>ID</td> <td>名字</td> <td>价格</td> </tr> </thead> <tbody> <tr v-for="f in fruits" :key="f.id" @click="onAddCart([f.id,f.name])"> <td>{{ f.id }}</td> <td>{{ f.name }}</td> <td>{{ f.price }}</td> </tr> <slot :goods="f"></slot> </tbody> </table> </div> </template> <script> export default { data(){ return{ fruits:[ { id:'01', name:'苹果~~🍎', price:'3.90' }, { id:'01', name:'西瓜~~🍉', price:'3.70' }, { id:'01', name:'葡萄~~🍇', price:'3.80' }, { id:'01', name:'橙子~~🍊', price:'3.50' }, { id:'01', name:'香蕉~~🍌', price:'3.30' }, ] } }, methods:{ onAddCart(params){ this.$emit('add-cart',...params) } } } </script> <style lang="scss" scoped> .fruit{ // li{ // list-style: none; // } width: 100%; // height: 100%; // background-color: plum; table{ width: 95%; // border-radius: 20px; margin: 0 auto; border: 1px bolid black; thead{ width: 100%; // border-radius: 20px; // background-color: blue; text-align: center; } tbody{ // border-radius: 20px; width: 100%; background-color: aliceblue; text-align: center; } } } </style>
**原理:**当子组件vm实例化时,获取到父组件传入的slot标签的内容,存放在vm.s l o t 中,默认插槽为 v m . slot中,默认插槽为vm.slot中,默认插槽为vm.slot.default,具名插槽为vm.s l o t . x x x , x x x 是插槽的名字,当组件执行渲染函数时候,遇到 s l o t 标签,使用 slot.xxx,xxx是插槽的名字,当组件执行渲染函数时候,遇到slot标签,使用slot.xxx,xxx是插槽的名字,当组件执行渲染函数时候,遇到slot标签,使用slot中的内容进行替换,此时可以为插槽传递数据,若存在数据,则就是作用域插槽