React Children 使用
React 有一个特殊的属性children, 主要用于组件需要渲染内容,但它并不知道具体要渲染什么内容,怎么会有这种使用场景?确实比较少,但并不是没有,比如弹出框。当你写一个弹出框组件的时候,你知道它要弹出什么吗?肯定不知道,只有使用的时候才知道。那为什么要写弹出框组件?虽然内容不一样,但框是一致的,居中啊,阴影啊,宽度啊,高度啊,每一个弹出框都一样,所以有必要形成一个组件,代码复用。框写好了,那到时候用的时候,具体的内容怎么放到框里面?那就要在框中占一个位置,如果有内容候就放到这个地方,占位置使用的就是children.
根据描述,children 最简单的使用场景就是一个组件中直接写this.props.children,调用这个组件的时候,再具体写内容。这里要注意的是组件调用方式,.假设包含children的组件叫theme, 那么调用的时候,就要在theme组件两个标签之间写内容,<theme><message/></theme>, 只有这样<message />才会被theme组件中的children 获取到。为什么要这要写?想一想html 标签, 只有在两个标签之间内容才被称之为children, 这里的children 也是同样的道理,只不过标签换成了组件。
使用create-react-app 创建一个项目 react-children,实践一下,要使用boostrap 提供样式, 所以 cd react-children && npm install bootstrap --save, 使用vs code 编辑器打开项目, 在index.js中引入bootstrap css 样式
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';// 添加bootstrap 样式
import 'bootstrap/dist/css/bootstrap.css'; ReactDOM.render(<App />, document.getElementById('root'));
在src 目录下创建一个简单的组件ThemeSelector, 它就是只包含this.props.children
import React from 'react';
export default function ThemeSelector(props) {
return (
<div className="bg-dark p-2">
<div className="bg-info p-2">
{props.children}
</div>
</div>
)
}
然后创建两个ThemeSelector要真正渲染的组件, ActionButton和Message
import React from "react";
export default function Message(props) {
return (
<div className={`h5 bg-${props.theme} text-white p-`}>
{props.message}
</div>
)
}
import React from "react";
export default function ActionButton(props) {
return (
<button className={` btn btn-${props.theme} m-`}
onClick={props.callback}>
{props.text}
</button>
)
}
在App.js中调用这三个组件,使ActionButton和Message 真正渲染到ThemeSelector 中
import React, { Component } from 'react';
import Message from "./Message";
import ActionButton from './ActionButton';
import ThemeSelector from './ThemeSelector'; export default class App extends Component {
constructor(props) {
super(props);
this.state = {
counter:
}
}
incrementCounter = () => {
this.setState({ counter: this.state.counter + });
} render() {
return <div className="m-2 text-center">
{/* 真正要渲染的内容入到<ThemeSelector>标签 */}
<ThemeSelector>
<Message theme="primary"
message={`Counter: ${this.state.counter}`} />
<ActionButton theme="secondary"
text="Increment" callback={this.incrementCounter} />
</ThemeSelector>
</div>
}
}
npm start 启动服务器,效果如下,非常简单,
综上所述,可以简单总结一下,children 只是一个占位符,使用children 属性的组件,它也只是提供了一个架子(容器),children真正的内容,只有在调用组件的时候才能确认。这么做的好处,就是架子(容器)的代码可以复用,这也给我们一个提示, 只要有多个组件的容器一致,就可以使用childern 属性。
我以前对children 属性的认知也仅限于此,直到最近,看了一本书,才知道React 还提供了一些操作children 的方法,进而知道了children 可以是任何内容, 这些方法正是为了children 属性量身定做的。重新认识一下children, 它可以是字符串,可以是函数,,可以是数组,可以是undefined , 可以是null, 可以是Boolean,几乎,你想到的都可以是children的内容。
<ThemeSelector>123</ThemeSelector>
<ThemeSelector>{undefined}</ThemeSelector>
<ThemeSelector>{null}</ThemeSelector>
<ThemeSelector>{(() => 'helloWorld')()}</ThemeSelector>
<ThemeSelector>{[4,5,6]}</ThemeSelector>
<ThemeSelector>{false} {true}</ThemeSelector>
只不过 null ,undefined,false, true 并不会渲染到页面上,由于提供给children 内容的各种各样,this.props.children的返回值也是不同,如果children没有获取到内容,它返回的就是undefined, 如果只有一个内容, 它返回的就是一个object, 如果有多个,它返回的就是数组。正是由于children的复杂性,React才提从提供了以下几个方法来帮我们正确地使用children 属性。
React.Children.map: 和数组的map 方法一致,接受children 和一个函数,返回map 后的children, 返回的是一个数组。函数的参数第一个是child组件,第二个是 index索引
React.Children.forEach: 和React.Children.map 的使用方法一致,只不过不返回内容
React.children.count: 接受children 作为参数,计算children的数量
React.children.only: 判断获取的children是不是只有一个,如果是,就返回这个children, 如果不是,则报错。
React.children.toArray: 把children 转化为数组,可以使用数组中的方法来操作children, 比如反转或删除
React.cloneElement: 克隆children, 为什么要克隆呢?因为获取到children 之后,它是只读的,并不能给它添加属性,如果想给children添加属性,那只能先复制一份到组件中,然后再添加属性,所以它接受两个参数,一个是children, 要复制的children, 一个是对象,相要添加的给children的属性。
简单写几个实例,熟悉一下这几个方法的用法,在ThemeSelector 组件中添加一个下拉列表示框来选择主题,来改变children ActionButton 和Message 的主题,使用是map 和cloneElement
import React, { Component } from 'react' export default class ThemeSelector extends Component {
state = { theme: 'primary' } setTheme = (event) => {
console.log(event.target.value)
this.setState({ theme: event.target.value });
} render() {
// map 和cloneElement 的使用
let modChildren = React.Children.map(this.props.children, (child) => {
return React.cloneElement(child, {
theme: this.state.theme
})
})
return (
<div children='bg-dark p-2'>
{/* 下拉列表,更改主题 */}
<div className='form-group text-left'>
<label className='text-white'>theme:</label>
<select className='form-control' value={this.state.theme}
onChange={this.setTheme}>
<option value='primary'>primary</option>
<option value='secondary'>secondary</option>
<option value='success'>success</option>
</select>
</div>
{/* map 和clone 后的children */}
<div className="bg-info p-2">
{modChildren}
</div>
</div>
)
}
}
map 的使用,由于chidren的属性都是直读的,所以不能直接使用forEach 来迭代添加属性,所以使用map 来迭代,用React.cloneElemnet 来复制每一个child,同时给它添加属性。cloneElement 只接受一个child component 和一个props 对象,这个props 对象会和child component 现有的属性进行合并, 最终,就是每一个child 获取到了theme 属性。
再在themeSeclector 组件的最下面加一个反转,使用toArray()
{/* map 和clone 后的children */}
<div className="bg-info p-2">
{modChildren}
</div> {/* toArray(), 转化为数组,然后使用数组的reserse 方法进行反转 */}
<div className="bg-info p-2">
{React.Children.toArray(this.props.children).reverse()}
</div>
加一个p元素,使用count 方法,显示有children的个数
<p>{React.Children.count(this.props.children)}</p>
还剩一个only, 只有一个children. 常用来判断children 是不是一个函数。如果我们children 需要用户提供一个函数的时候,它有可能提供多个元素,所以使用only 就会报错。如果themeSelect的组件是
{this.props.children()} , 使用{React.children.only(this.props.children)()}
React Children 使用的更多相关文章
- React中props.children和React.Children的区别
在React中,当涉及组件嵌套,在父组件中使用props.children把所有子组件显示出来.如下: function ParentComponent(props){ return ( <di ...
- 对React children 的深入理解
React的核心为组件.你可以像嵌套HTML标签一样嵌套使用这些组件,这使得编写JSX更加容易因为它类似于标记语言. 当我刚开始学习React时,当时我认为“使用 props.children 就这么 ...
- React.Children详解
React.Children提供了处理this.props.children的工具,this.props.children可以任何数据(组件.字符串.函数等等).React.children有5个方法 ...
- react children技巧总结
在使用该技巧时,建议先看一下相关的知识,点我查看 假如使用该属性时,想把父组件的所有属性及部分方法传递给子组件,该怎么办呢?看代码 const Child = ({ doSomething, valu ...
- [React] Compound Component (React.Children.map & React.cloneElement)
Imaging you are building a Tabs component. If looks like: <Tabs> <TabList> <Tab> o ...
- [React] Understand React.Children Utilities
The data contained in this.props.children is not always what you might expect. React provides React. ...
- React源码 React.Children
children是什么意思呢?就是我们拿到组件内部的props的时候,有props.children这么一个属性,大部分情况下,我们直接把 props.children 渲染到 JSX 里面就可以了. ...
- React: 通过React.Children访问特定子组件
一.简介 React中提供了很多常用的API,其中有一个React.Children可以用来访问特定组件的子元素.它允许用来统计个数.map映射.循环遍历.转换数组以及显示指定子元素,如下所示: va ...
- React源码解析之React.Children.map()(五)
一,React.Children是什么? 是为了处理this.props.children(this.props.children表示所有组件的子节点)这个属性提供的工具,是顶层的api之一 二,Re ...
随机推荐
- JDBC连接池的九种查询
package JDBC_Demo; import java.sql.SQLException; import java.util.List; import java.util.Map; import ...
- Sublime Text2中的快捷方式及html各种标签(待完善)
快捷方式 1.xhtml+tab 2.自动补全标签 Alt + . 补全标签 标签 1.<p>段落标签 ,前后换行 <h1.2.3.4.5>标题标签 h1最大,一级标题 2. ...
- 导入数据任务(id:373985)异常, 错误信息:解析导入文件错误,请检查导入文件内容,仅支持导入json格式数据及excel文件
小程序导入,别人导出的数据库json文件,错误信息如下: 导入数据库失败, Error: Poll error, 导入数据任务(id:373985)异常,错误信息:解析导入文件错误,请检查导入文件内容 ...
- 解决github等外国网站突然无法链接的问题
问题描述:可以ping通但是通过游览器不能访问. 直接用这个方法:
- Linux终端图形库编程
/* *drawWin.c */ #include<stdio.h> #include<stdlib.h> #include<string.h> #include& ...
- Unix/Linux系统下的nobody用户是什么?
1.Windows系统在安装后会自动建立一些用户帐户,在Linux系统中同样有一些用户帐户是在系统安装后就有的,就像Windows系统中的内置帐户一样. 2.它们是用来完成特定任务的,比如nobody ...
- python jenkins api
#!/usr/bin/pythonimport sys, timeimport shutil, commands#coding=utf-8 import sysreload(sys)sys.setde ...
- html中利用flex容器书写的布局样式
首先页面基本样式见下图: 如有兴趣可以打开https://migloo.gitee.io/front 或者 https://www.igloo.xin/front 进行查看
- 源码编译安装使用glusterfs+heketi安装使用
注:使用源码安装的原因主要是使用yum安装glusterfs服务端时出现一些依赖库问题 准备3台glusterfs服务器(官方也建议至少3台,防止发生脑裂),并在各个服务器的/etc/hosts下面添 ...
- Python3注解+可变参数实现
一.说明 1.1 关于注解 关于注解这个东西,最早是在大学学java的时候经常会看到某些方法上边@override之类的东西,一方面不知道其作用但另一方面似乎去掉也没什么影响,所以一直都不怎么在意. ...