「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」。
插槽,初学者的噩梦,也是我曾经的噩梦,但业务开发中写多了,回过头总结的时候,发现也不过如此。
问题
27.说一下你对 vue 插槽的理解
一个再复杂的 Vue 组件,都是由三部分组成的:prop、event、slot。
插槽(slot)就是构成 Vue 组件的一部分而已。
插槽通俗的理解就是“占坑”,在组件模板中占好了位置,当使用该组件标签时候,组件标签里面的内容就会自动填坑(替换组件模板中 slot 位置)。
当初还看到过一种理解,让我豁然开朗,把 slot 和 prop 类比:
js -> prop
html -> slot
prop 和 slot 都可以理解成外部传入参数,prop 传的是 js 代码, slot 传的是 html 代码,最终的目的都是父组件去控制子组件做一些事情,只不过 prop 控制的是 js 逻辑, slot 控制的是 html 结构和样式。
插槽基本使用
<base-content> qwer </base-content>
如果直接在一个自定义组件内部写 html,将不会生效。
这时就需要使用插槽,才能把 html 插入到组件中的 slot 标签中。
子组件内:
<div>
<slot></slot>
</div>
具名插槽
一个组件可以有多个插槽,通过 slot 标签的 name 属性来区分。
父组件通过,slot="name"(旧语法),v-slot:name或#name(新语法) 的方式添加内容:
子组件内:
<div class="base-content">
<slot name="header"></slot>
<slot name="main"></slot>
<slot name="footer"></slot>
</div>
父组件内:
<base-content>
<div slot="header">我是header</div>
<template #main>我是main</template>
<template v-slot:footer>我是footer</template>
</base-content>
28.父组件能否通过插槽的形式使用子组件的数据?
直接使用不能,使用作用域插槽能 直接使用
子组件内:
<div class="base-content">
<slot></slot>
</div>
data() {
return {
innerContent: 'qwer'
}
}
父组件:
<base-content> {{ innerContent }} </base-content>
就报错了:
原因是:
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。 -- vue 文档
作用域插槽
子组件内:
<div class="base-content">
<slot name="header" :innerContent="innerContent"></slot>
</div>
data() {
return {
innerContent: '我是innerContent'
}
}
父组件内:
<base-content>
<template v-slot:header="headerData">{{ headerData.innerContent }}</template>
</base-content>
这样的写法就和使用 props 传参非常像了,不过是从子组件的 slot 标签上向父组件传递,在父组件内通过 v-slot 接收。
注意,作用域插槽以前的写法是 slot-scope,已经在 2.6.0 版本被废弃了,写插槽最好都用 v-slot。
29. $slots 和 $scopedSlots 是干嘛用的?
它们都是 vue 实例上的属性:
$slots用来访问被 插槽分发 的内容。
$scopedSlots用来访问作用域插槽。
在子组件内部判断父组件插槽使用情况的时候,这两个属性很有用,
比如下面这两段代码,取自于 element-ui 的 alert 组件和 tree 组件。