写在前面:组件有各自编译作用域---父级模板里的所有内容都是在父级作用域中编译的,子模板里的所有内容都是在子作用域中编译的
理解插槽
vue文档里说,将<slot>
元素作为承载分发内容的出口,乍一看,确实不好理解。
我对slot的通俗理解:
因为组件有各自编译作用域,直接在父级模板里的子级标签中间填充内容是无效的,毕竟子级标签是我们自己创建出来的,不是HTML自带标签
//父组件
<template>
<div>
<Child><p>儿子,这是我要写给你的内容...</p></Child> //这是在父组件中定义的内容,子组件无法收到
</div>
</template>
如果你确实想在这中间填充内容,怎么办?
那就得父子组件间建立通信。预先在相应的子组件中声明一下,给你要填充的内容留个坑位,于是就有了<slot></slot>
//子组件
<template>
<div>
<slot></slot> //给父组件要填充的内容留个坑位,相当于父子组件建立了通信
</div>
</template>
//父组件
<template>
<div>
<Child><p>儿子,我准备给你打生活费了</p></Child> //父子组件建立通信后,子组件可以接受到填充内容,并在后续渲染
</div>
</template>
可是如果希望根据坑位坐标,快速找到位置
那就需要在子组件中通过<slot name="xxx"></slot>
提前标注,
在父组件中在要显示的标签里添加slot="xxx"'属性,表示这条信息需绑定到某一个具体的坑位
//父组件
<template>
<div>
<Child>
<span>5000 or </span>
<span slot='ok'>10000</span>
</Child>
</div>
</template>
//子组件
<template>
<div>
<slot></slot> //默认插槽,将匹配<span>5000 or </span>
<slot name="ok"></slot> //具名插槽,将匹配<span slot='ok'>10000</span>
</div>
</template>
如果子组件中的slot标签中有内容表示什么意思? 父子组件已建立好通信,可父组间鸽了子组件,没有“填充内容”,子组件则会显示默认内容
笔记部分
理解了插槽之后,就开始基于Vue3做点正式的笔记,(可以点击blog.csdn.net/marendu/art…)
在Vue3中,用template
标签包裹要填充的内容,v-slot
属性也需定义在template
标签上,只有一种例外情况,就是默认插槽
v-slot:
的语法糖是#
,但后面必须有插槽名,例如v-slot:default
等价于 #default
插槽有三种
默认插槽
//父组件 (Child外层有templat>div标签,此处省略,方便观看)
<Child>
<template v-slot:default>
<p></p>
</template>
</Child>
//也可以是这样,属于例外情况
//父组件
<Child v-slot:default>
<p></p>
</Child>
具名插槽
//父组件
<Child>
<template v-slot:xxx> //绑定名称
<p></p>
</template>
<template v-slot:[动态插槽名]> //动态插槽名,即通过data的属性值来控制插槽名,以动态更新
<p></p>
</template>
</Child>
//子组件
<template>
<div>
<slot name=xxx></slot>
<slot name=xxx></slot>
</div>
</template>
作用域插槽
作用域插槽的作用即延展子模板中数据的作用域,使得在父级模板中也可使用子模板中的数据
//父组件
<Child>
<template v-slot:num="slotProps">
<p>{{slotProps.value}}</p> //访问子组件中“num”插槽的value属性值
</template>
<template v-slot:default="slotProps">
<p>{{slotProps.price}}</p> //访问子组件中对应默认插槽的price属性值
</template>
<template v-slot:name="{uname: myname}">
<p>{{myname}}</p> //访问子组件中对应“name”插槽的uname属性值,采用解构赋值的方式
</template>
</Child>
//子组件
<template>
<div>
<slot name="num" :value="value"></slot>
<slot :price="price"></slot>
<slot name="name" :uname="uname"></slot>
</div>
</template>
插槽的实现原理(/过程):
当子组件vm实例化时,获取到父组件传入的slot标签的内容,存放在vm.$slot中,默认插槽
为vm.$slot.default,具名插槽为vm.$slot.xxx,xxx 为插槽名,当组件执行渲染函数时候,
遇到slot标签,使用$slot中的内容进行替换,此时可以为插槽传递数据,若存在数据,
则可称该插槽为作用域插槽
参考:
Vue入门之slot属性 - 简书 (jianshu.com)
「2021」高频前端面试题汇总之Vue篇 (上) (juejin.cn)
vue2到vue3中插槽slot变化详解---从slot,slot-scope到v-slot的变化_marendu的博客-CSDN博客