10. 说说你对slot的理解?slot使用场景有哪些?slot的原理是?
什么是slot
在HTML中slot元素,是web组件内的一个占位符,可以在后期使用时使用自己的标记语言
html
<!--定义-->
<template id="element-details-template">
<slot name="element-name">Slot template</slot>
</template>
<!--使用-->
<element-details>
<span slot="element-name">1</span>
</element-details>
<element-details>
<span slot="element-name">2</span>
</element-details>
js
customElements.define('element-details',
class extends HTMLElement {
constructor() {
super();
const template = document
.getElementById('element-details-template')
.content;
const shadowRoot = this.attachShadow({mode: 'open'})
.appendChild(template.cloneNode(true));
}
})
vue中的slot
在vue中slot称为插槽,可以理解为在组件模板中占好了位置,当使用该组件标签时,组件标签将里面的内容就会自动填坑(替换组件模板中slot的位置)
使用场景
通过插槽可以让用户可以拓展组件,去更好地复用组件和对其做定制化处理
如果父组件在使用到一个复用组件的时候,获取这个组件在不同的地方有少量的更改,如果去重写组件是一件不明智的事情
通过slot插槽向组件内部指定位置传递内容,完成这个复用组件在不同场景的应用
比如布局组件、表格列、下拉选、弹框显示内容等
分类
默认插槽
子组件用<slot>
标签来确定渲染的位置,标签里面可以放DOM结构,当父组件使用的时候没有往插槽传入内容,标签内DOM结构就会显示在页面
父组件在使用的时候,直接在子组件的标签内写入内容即可
html
<!--子组件-->
<template>
<slot>
<p>插槽后备的内容</p>
</slot>
</template>
html
<!--父组件-->
<template>
<Child>
<div>默认插槽</div>
</Child>
</template>
具名插槽
子组件用name属性表示插槽名字,不传为默认插槽
父组件中在使用时在默认插槽的基础上加上slot属性,值为子组件插槽name属性值
html
<!--子组件-->
<template>
<slot name='content'>插</slot>
</template>
html
<!--父组件-->
<template v-slot:content>具名插槽</template>
<!--或者 简写-->
<template #content>具名插槽</template>
作用域插槽
插槽的内容无法访问到子组件的状态
然而在某些场景下插槽的内容可能想要同时使用父组件域内和子组件域内的数据。要做到这一点,我们需要一种方法来让子组件在渲染时将一部分数据提供给插槽。
html
<!-- <MyComponent> 的模板 -->
<div>
<slot :text="greetingMessage" :count="1"></slot>
</div>
作用域-默认插槽
html
<MyComponent v-slot="slotProps">
{{ slotProps.text }} {{ slotProps.count }}
</MyComponent>
可以将作用域插槽类比成传入子组件的函数
js
Mycomponent({
default: (slotProps) => {
return `${slotProps.text} ${slotProps.count}`
}
})
function MyComponent(slots) {
const hw = 'hello'
return `<div>${
slot.default({text: hw, count: 1})
}</div>`
}
可以在v-slot
中使用解构
html
<Mycomponent v-slot='{text, count}'>
<div>{{text}}{{count}}</div>
</MyComponent>
作用域 - 具名插槽
具名作用域插槽的工作方式也是类似的,插槽 props 可以作为 v-slot 指令的值被访问到
html
<MyComponent>
<template #header="headerProps">
{{ headerProps }}
</template>
<template #default="defaultProps">
{{ defaultProps }}
</template>
<template #footer="footerProps">
{{ footerProps }}
</template>
</MyComponent>
name是vue的保留属性,不会作为props传给插槽