slot是HTML
元素 , 是 Web 组件内的一个占位符。该占位符可以在后期使用自己的标记语言填充,这样您就可以创建单独的 DOM 树,并将它与其它的组件组合在一起。这个是官方解释看起来很晦涩,用人话说的意思是“Slot插槽是个占位符(就是一个占位置的),它可以和其它组件一起合用,就是他是可以复用,比如一个模态框组件我在底部按钮那里加了个插槽,如果别人引用那个组件,不修改那底部按钮就按组件里设置的使用,如果加上slot的name就是启用插槽对底部按钮进行修改,你可以去掉按钮或者修改按钮的个数都全凭君意”。
各位是不是很奇怪我们说插槽为什么讲template,是不是要说埃尔斯在挂羊头卖狗肉,各位稍安勿躁,听我娓娓道来。在HTML中solt一般与template合用,做成一个个可以复用的组件。
1、 标记用作容纳页面加载时对用户隐藏的 HTML 内容的容器。如果您有一些需要重复使用的 HTML 代码,则可以使用
标记。也就是说
包裹的内容是隐藏的在浏览器中不会渲染出来
2、 中的内容可以稍后使用 JavaScript 呈现。也就是说让
包裹的内容在浏览器中渲染需要使用js去创造一个dom节点去挂载到HTML中任意一处dom下就能看得到
里的内容了。
代码如下所示:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<template id="element-details-template">
<style>
details {font-family: "Open Sans Light", Helvetica, Arial, sans-serif }
.name {font-weight: bold; color: #217ac0; font-size: 120% }
h4 {
margin: 10px 0 -8px 0;
background: #217ac0;
color: white;
padding: 2px 6px;
border: 1px solid #cee9f9;
border-radius: 4px;
}
.attributes { margin-left: 22px; font-size: 90% }
.attributes p { margin-left: 16px; font-style: italic }
style>
<details>
<summary>
<code class="name"><<slot name="element-name">NEED NAMEslot>>code>
<i class="desc"><slot name="description">NEED DESCRIPTIONslot>i>
summary>
<div class="attributes">
<h4>Attributesh4>
<slot name="attributes"><p>Nonep>slot>
div>
details>
<hr>
template>
<element-details>
<p>默认模板----p>
element-details>
<element-details>
<p>wdfwerwerp>修改传递下来数据---
<a slot="attributes"><p>wwwe334eep>a>
element-details>
body>
<script>
customElements.define('element-details',
class extends HTMLElement {
constructor() {
super();
var template = document
.getElementById('element-details-template')
.content;
const shadowRoot = this.attachShadow({mode: 'open'})
.appendChild(template.cloneNode(true));
}
})
script>
html>
运行结果如下所示:
第一个是默认的模板组件显示,没有任何改变渲染出来。
第二个是改了attributes的slot内容,显示了我修改的内容。
在引用的时候组件里包裹的没有加slot属性的内容没有被渲染出来,如我在代码的注释里所描述的一样。
现在说完执行完的结果我们来聊聊组件里里的事,这里面到底干了啥?
1)里的内容没有被js创造成element-details组件前是没有渲染的,不然就会生成三块内容,而不是两块。
2)里有
等标签和``
标签,进行混用,也就是说
标签可以和其他标签混用生成业务组件。
3)]用
标签和
标签的属性生成一个 命名的槽 (named slots):
包裹 命名的槽 (named slots) 在
元素中。<element-details>
<p>wdfwerwerp>修改传递下来数据---
<a slot="attributes"><p>wwwe334eep>a>
element-details>
在vue中使用插槽有两种半方式。
标签包裹。建立一个
的组件,它的模板代码如下:
这个和web component里一样,有一个
标签,这里
元素是一个插槽的插口,标示了父元素提供的插槽内容将在哪里被渲染。
这里要引用这个FancyButton组件实现这个插槽作用的代码如下所示:
Click me!
最终渲染出的 DOM 是这样:
插槽内容还可以是任意合法的模板内容。例如我们可以传入多个元素,甚至是组件,就是我们想插什么内容都可以。
表现形式代码如下:
这里的name=“header”,name="footer"就是具名的slot.
使用 JavaScript 函数可能更有助于你来理解具名插槽:
// 传入不同的内容给不同名字的插槽
BaseLayout({
header: `...`,
default: `...`,
footer: `...`
})
// 渲染插槽内容到对应位置
function BaseLayout(slots) {
return (
`
${slots.header}
${slots.default}
`
)
}
代码如下:
Header content
Default slot content
Footer content
{{ slotProps.item.text }}
Mouse position: {{ x }}, {{ y }}
在普通web组件中和vue中的使用都已介绍,在React中呢,又该怎么样呢?
在我们React中组件里直接包裹一些html标签,html标签里的内容会不会显示呢?来我们来上代码:
import React, { Component } from 'react'
export default class MySlot extends Component {
render() {
return (
<div>
<div>MySlot--Parent</div>
<Child>
<p>111111</p>
</Child>
</div>
)
}
}
class Child extends Component {
render() {
return (
<div>Child</div>
)
}
}
上面代码运行结果如下图所示:
由此可见 111111
并没有渲染出来。那么我们要使它渲染出来,得怎么修改呢?欲知后事如何请听下回。。。别急,我现在道来。组件中props有一个固定的children属性去在Child组件中占一个位,做成插槽。代码如下所示:
import React, { Component } from 'react'
export default class MySlot extends Component {
render() {
return (
<div>
<div>MySlot--Parent</div>
<Child>
<p>111111</p>
</Child>
</div>
)
}
}
class Child extends Component {
render() {
return (
<div>
<div>Child</div>
{/* vue中有slot这个标签去表示插槽,React中是props属性中固定的children属性表示 */}
<div>{this.props.children}</div>
</div>
)
}
}
运行结果:
由此11111给渲染出来了。
那如果父组件中传递的html比较多呢又会有什么样的效果呢,上代码:
import React, { Component } from 'react'
export default class MySlot extends Component {
render() {
return (
<div>
<div>MySlot--Parent</div>
<Child>
<div><p>111111</p> </div>
<div><h2>222222</h2> </div>
<div><i>333333</i> </div>
</Child>
</div>
)
}
}
class Child extends Component {
render() {
console.log('this.props.children',this.props.children)
return (
<div>
<div>Child</div>
{/* vue中有slot这个标签去表示插槽,React中是props属性中固定的children属性表示 */}
<h1>this.props.children获取的是一个父组件传递过来的全部dom</h1>
<div>{this.props.children}</div>
<h1>类似于vue中的具名插槽显示</h1>
<div>{this.props.children[0]}</div>
<div>{this.props.children[2]}</div>
<div>{this.props.children[2]}</div>
<div>{this.props.children[1]}</div>
</div>
)
}
}
上述代码渲染结果如下所示:
由上图结果可知:
1)this.props.children 获取的是父组件传递过来的整个dom生成的数组,并每个并列的html元素是其的一个元素,上面代码是传递了3个div包裹的元素,所以this.props.children生成了也length为3的数组。
2)在页面中的展示顺序是和Child中this.props.children的数组下标有关和父组件传递过来的顺序没关。
至此插槽的相关知识也总结的七七八八了,我就抛砖引玉了,欢迎各位大佬莅临指导。