插槽是组件核心概念之一:状态、插槽、生命周期
1.普通插槽
通过props上的children属性,能拿到父组件传递进来的元素
import PropTypes from 'prop-types';
import React from 'react';
const Dialog = function Dialog(props) {
// 获取传递的属性和插槽信息
let { title, content, children } = props;
children = React.Children.toArray(children);
return <div className="dialog-box" style={{ width: 300 }}>
<div className="header" style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center'
}}>
<h2 className="title">{title}</h2>
<span>X</span>
</div>
<div className="main">
{content}
</div>
{children.length > 0 ?
<div className="footer">
{children}
</div> :
null
}
</div>;
};
export default Dialog;
2.具名插槽
父组件传递插槽内容时,在children元素上添加自定义属性,将其标记为具名插槽,一般属性名是slot
要对children的类型做处理:可以基于 React.Children 对象中提供的方法,对props.children做处理
children上提供了一个
toArray方法,可以帮我们把children转为数组
import PropTypes from 'prop-types';
import React from 'react';
const DemoOne = function DemoOne(props) {
let { title, x, children } = props;
// 如果只要一个children,toArray能帮你转为数组
children = React.Children.toArray(children);
let headerSlot = [],
footerSlot = [],
defaultSlot = [];
children.forEach(child => {
// 传递进来的插槽信息,都是编译为virtualDOM后传递进来的「而不是传递的标签」
let { slot } = child.props;
if (slot === 'header') {
headerSlot.push(child);
} else if (slot === 'footer') {
footerSlot.push(child);
} else {
defaultSlot.push(child);
}
});
return <div className="demo-box">
{headerSlot}
<br />
<h2 className="title">{title}</h2>
<span>{x}</span>
<br />
{footerSlot}
</div>;
};
使用时:
import Dialog from './components/Dialog';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<>
<Dialog title="友情提示" content="大家出门做好个人防护!" />
<Dialog content="我们一定要好好学React!">
<button>确定</button>
<button>很确定</button>
</Dialog>
</>
);