React 写组件,通常是组件与组件之间相互引用,组合成一个树状的结构,进行渲染。
我们自己封装组件的时候,为了统一组件顶层数据来源
和 在组件内部常常需要自定义一些东西
,做类似于插槽的功能。直接将 jsx 内容插入到组件内部,而不是通过组件引入的方式,引入组件内部。
<App>
<About name='name'></About>
<About name='fisrtName'></About>
</App>
children 一般用的比较少,但是在组件封装时候,用处就比较大了。About 组件集合会通过 App 组件的 props.children 中访问到。
children
- 对应关系
props.children 是 react 元素集合,可直接渲染在 render 函数中。props 与父组件的插槽位置元素相对应。如果有过 Vue 经验,对应关系很好理解。
- 本质
对象,如果看过 React 源码,就知道 React 其实就是一个个对象,来描述这个组件应该如何渲染。
- 访问
通过 props 直接访问
- 改造 children
api:
- React.Children API
- React.cloneElement
上面提到 children 本质是一个模板 React 元素对象,那么我们应该如何这些模板就可通过 props 访问来改造重新组装来渲染新的 React 组件, 达到了使用
const newEl = React.cloneElement(child, newchildProps)
一个简单的例子
使用 Create-React-App 创建一个例子
// main.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
// components
import About from "./components/About";
ReactDOM.render(
<React.StrictMode>
<App>
<About name='name'></About>
<About name='fisrtName'></About>
</App>
</React.StrictMode>,
document.getElementById("root")
);
App 组件是主要渲染的组件,它的插槽位置有两个 React 元素,他们在 App 组件内部使用 props.children 可访到该集合。
<About name='name'></About>
<About name='fisrtName'></About>
About 组件的实现很简单, 注意:只是在插槽或者children位置,传入 name 的 props, 并没有传入 haxi 的 props,但是使用了 haxi, 好像这个haxi 成了魔术数字, 这也是接下来需要改造的 App 组件的地方:
import React from 'react';
export default function About(props){
return <div>{props.name}-{props.haxi}</div>
}
在 App 组件内部实现 props 的内容改造,然后克隆一个新的元素渲染,其实我们这里只是将 props.children 当成了模板,在渲染的时候是重新改造了新元素,下面我们实现这个简单的改造过程:
import React from "react";
import logo from "./logo.svg";
import "./App.css";
function App(props) {
// 获取 props
const { children } = props;
// 遍历生成新的 El 集合
const child = React.Children.map(children, (item, index) => {
const childProps = {
...item.props,
// 使用 index 赋值 haxi 属性
haxi: index
};
// 使用 元素和新的 props 克隆一个新的 react 元素
return React.cloneElement(item, childProps);
});
return (
<div className='App'>
<header className='App-header'>
// 直接渲染新的 child
{child}
</a>
</header>
</div>
);
}
export default App;
优点
- 组件全部放在顶层,数据来源直接在顶层定义,方便快捷
- 结构更加明确,使用简单,没有更多层次的组件引用
- 充分的认识 React 本质和 React.Children + props.children API