【React】插槽渲染机制
目录
- 通过 children 属性结合条件渲染
- 通过 children 和 slot 属性实现具名插槽
- 通过 props 实现具名插槽
在 React 中,并没有直接类似于 Vue 中的“插槽”机制(slot)。但是,React 可以通过
props
和
children
来实现类似插槽的功能,允许你将组件的内容进行灵活插入和替换。
通过 children 属性结合条件渲染
通过 children 来传递任意数量的子元素,然后在组件内部通过位置进行条件渲染,从而实现插槽功能。
Layout 组件通过 children
渲染传递给它的所有子元素,而这些子元素可以是任何内容,类似于 Vue 中的默认插槽。虽然在某些情况下,children
已经是一个数组(例如多个子元素的情况),但 React.Children.toArray
会确保你始终获得一个标准化的数组(过滤掉null、undefined
等数据)。
//子组件
const Layout = ({ children }) => {
children = React.Children.toArray(children);
console.log(children,'children')
return (
<div className="layout">
<header>Header</header>
<main>{children}</main> {/* 这里的 children 就是父组件传递进来的内容 */}
<footer>Footer</footer>
</div>
);
};
//父组件
const App = () => {
return (
<Layout>
<h1>Hello, React!</h1>
<p>This is the main content of the page.</p>
</Layout>
);
};
打印出children
,就是父组件标签里内容编译成的virtualDOM。
通过 children 和 slot 属性实现具名插槽
在标签上加slot
来标记标签
//父组件
root.render(
<>
<DemoOne title="REACT好好玩哦" x={10}>
<span slot="footer">我是页脚</span>
<span>哈哈哈哈</span>
<span slot="header">我是页眉</span>
</DemoOne>
</>
);
子组件根据children
属性中的slot
来区分插槽
//子组件
const DemoOne = function DemoOne(props) {
let { title, x, children } = props;
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>;
};
通过 props 实现具名插槽
显式传递 props 来模拟具名插槽,传递不同的内容到特定的插槽位置
const DemoOne = ({ title, x, children, footer, header }) => {
return (
<div className="demo-box">
<h1>{title}</h1>
<div>{header}</div> {/* 渲染具名插槽 header */}
<div>{children}</div> {/* 渲染默认插槽 */}
<div>{footer}</div> {/* 渲染具名插槽 footer */}
</div>
);
};
const App = () => {
return (
<DemoOne title="REACT好好玩哦" x={10} footer={<span>我是页脚</span>} header={<span>我是页眉</span>}>
<span>哈哈哈哈</span>
</DemoOne>
);
};