vue里模板复用使我们的效率大大提升了,可是在复用的时候都需要保留框架而更改内容,这时候就需要用到插槽了
插槽分为:匿名插槽,具名插槽和作用域插槽 (以填詩詞爲例)
匿名插槽:
子模板:
<template>
<div class="slot">
<span>一朝选在君王侧。</span>
</template>
引入模板的父组件:
<template>
<div class="home">
<v-slot class="fp">
<span>天生丽质难自弃,</span>
</v-slot>
</div>
</template> // 使用
import vSlot from '../components/slot.vue' //引入
export default {
components: { vSlot } //注册
}
效果:
这时候你会发现 哎 我的 “天生丽质难自弃,” 呢?别急 咱先试试匿名插槽
引入父组件不动 只需在子模板合适位置加上一<slot></slot>标签即可
<template>
<div class="slot">
<slot></slot>
<span>一朝选在君王侧。</span>
</div>
</template>
效果:
是不是 so easy ! 那如果我不小心加了很多的<slot></slot>标签会怎样?
比如这样?
<template>
<div class="slot">
<slot></slot>
<slot></slot>
<span>一朝选在君王侧。</span>
<slot></slot>
<slot></slot>
<slot></slot>
</div>
</template>
效果:
那天生丽质 真 · 难自弃 了 由此匿名插槽的弊端暴露无疑:在使用模板时填入的内容都会去找匿名插槽,找到一个就把内容填入,有几个就填几个,就无法避免重复。
快看!这时候具名插槽出现了
具名插槽:
子模板:
<template>
<div class="slot">
<p>
<slot name="footer">
<span>footer-显示默认内容</span>
</slot>
</p>
<p>
<slot name="header">
<span>header-显示默认内容</span>
</slot>
</p>
<p>
<slot></slot>
<span>一朝选在君王侧。</span>
</p>
</div>
</template>
父组件:
<template>
<div class="home">
<v-slot class="fp">
<template v-slot:header>
</template>
<template #footer>
</template>
<span>天生丽质难自弃,</span>
</v-slot>
</div>
</template>
效果:
有个有意思的现象:
在使用具名插槽的时候,我明明先用的header 可为什么footer在前面显示呢?
其实显示的先后的关键在于子模板的排列先后 这和父组件的使用先后无关
也就是说虽然我footer名字起的是差了点,但我在子模板中选了个第一排的好位置,所以显示内容就在第一排(我骄傲 !╭(╯^╰)╮)
那么又一个问题来了:每次使用模板时总不能内容是固定的吧 那具名插槽里的初始默认内容需要根据内容更改的呀
子模板:
<template>
<div class="slot">
<slot name="footer">
<span>footer-显示默认内容</span>
</slot>
<slot name="header">
<span>header-显示默认内容</span>
</slot>
<p>
<slot></slot>
<span>一朝选在君王侧。</span>
</p>
</div>
</template>
父组件:
<template>
<div class="home">
<v-slot class="fp">
<template v-slot:header>
<span>养在深闺人未识。</span>
</template>
<template #footer>
<span>杨家有女初长成,</span>
</template>
<span>天生丽质难自弃,</span>
</v-slot>
</div>
</template>
效果:
由此可见:
<template v-slot:header> </template>
<template #header> </template>
这两种还像都可以找到对应名称的插槽,
其实就是全称与简写的区别了 v-slot:可简写成 #
且在里面写入的内容就会取代默认内容 是不是炒鸡简单?
这时候我里面内容是可变的且数据在子模板里怎么办?看!作用域插槽来了
作用域插槽:
子模板:
:msg="content" 【msg可用任意名称 我这里用msg】【content是data里定义的数据名称】
这里提一下 如果不小心写成 msg="content" ?那么传递出去的就是content这个字符串数据了
比如你想打个招呼 又不想在data里重新定义 后面也不需要更改 可写成 msg="hello" 把hello这个字符串传递出去
<template>
<div class="slot">
<p>
<slot name="footer">
<span>footer-显示默认内容</span>
</slot>
<slot name="header">
<span>header-显示默认内容</span>
</slot>
</p>
<p>
<slot></slot>
<span>一朝选在君王侧。</span>
</p>
<p>
<slot name="content" :msg="content"></slot>
</p>
</div>
</template>
字幕版字符串数据数据:
父组件:
<template>
<div class="home">
<v-slot class="fp">
<template v-slot:header>
<span>养在深闺人未识。</span>
</template>
<template #footer>
<span>杨家有女初长成,</span>
</template>
<span>天生丽质难自弃,</span>
<template #content="msg">
<span>{
{msg.msg}}</span>
</template>
</v-slot>
</div>
</template>
效果:
在展示数据时 msg.msg是不是很烦人呢?如果字段不是字符串而是对象,数组对象甚至嵌套好几次 难道我要一层一层点下去吗?
如此 那我们试一下进阶版
子模板:
注意点:【使用v-for时无需绑定key值,会报错。有知道原理的大佬望不吝赐教】
<template>
<div class="slot">
<p>
<slot name="footer">
<span>footer-显示默认内容</span>
</slot>
<slot name="header">
<span>header-显示默认内容</span>
</slot>
</p>
<p>
<slot></slot>
<span>一朝选在君王侧。</span>
</p>
<p>
<slot name="main" v-for="item in list" :msg="item"></slot>
</p>
</div>
</template>
子模板数组数据:
父组件:
这里原理其实很简单 就是子模板遍历数组 并把遍历的每一项放到msg里然后传递给父组件
父组件接收msg并结构取值 然后展示
<template>
<div class="home">
<v-slot class="fp">
<template v-slot:header>
<span>养在深闺人未识。</span>
</template>
<template #footer>
<span>杨家有女初长成,</span>
</template>
<span>天生丽质难自弃,</span>
<template v-slot:content="content">
<span>{
{content.content}}</span>
</template>
<template #main="{msg}">
<span>{
{msg}}</span>
</template>
</v-slot>
</div>
</template>
效果:
总结:
所以作用域插槽使用的终极形式就是
<template #main="{msg}"><span>{ {msg}}</span></template>
原本 v-slot:main="msg" 进化成 #main="{msg}" 【简写+解构】当然随着数据格式的复杂解构也可以嵌套很多层,或者解构某一位置上的目标值