React之插槽

70 阅读1分钟

插槽是组件核心概念之一:状态、插槽、生命周期

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>
    </>
);