博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
React Children 使用
阅读量:5291 次
发布时间:2019-06-14

本文共 5366 字,大约阅读时间需要 17 分钟。

  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(
, document.getElementById('root'));

  在src 目录下创建一个简单的组件ThemeSelector, 它就是只包含this.props.children

import React from 'react'; export default function ThemeSelector(props) {    return (        
{
props.children}
)}

  然后创建两个ThemeSelector要真正渲染的组件, ActionButton和Message

import React from "react";export default function Message(props) {    return (        
{props.message}
)}
import React from "react";export default function ActionButton(props) {    return (            )}

  在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: 0    }  }  incrementCounter = () => {    this.setState({ counter: this.state.counter + 1 });  }  render() {    return 
{
/* 真正要渲染的内容入到
标签 */}
}}

  npm start 启动服务器,效果如下,非常简单,

  综上所述,可以简单总结一下,children 只是一个占位符,使用children 属性的组件,它也只是提供了一个架子(容器),children真正的内容,只有在调用组件的时候才能确认。这么做的好处,就是架子(容器)的代码可以复用,这也给我们一个提示, 只要有多个组件的容器一致,就可以使用childern 属性。

   我以前对children 属性的认知也仅限于此,直到最近,看了一本书,才知道React 还提供了一些操作children 的方法,进而知道了children 可以是任何内容, 这些方法正是为了children 属性量身定做的。重新认识一下children, 它可以是字符串,可以是函数,,可以是数组,可以是undefined , 可以是null, 可以是Boolean,几乎,你想到的都可以是children的内容。

123
{undefined}
{
null}
{(() => 'helloWorld')()}
{[4,5,6]}
{
false} {
true}

  只不过 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 (
{
/* 下拉列表,更改主题 */}
{
/* map 和clone 后的children */}
{modChildren}
) }}

  map 的使用,由于chidren的属性都是直读的,所以不能直接使用forEach 来迭代添加属性,所以使用map 来迭代,用React.cloneElemnet 来复制每一个child,同时给它添加属性。cloneElement 只接受一个child component 和一个props 对象,这个props 对象会和child component 现有的属性进行合并, 最终,就是每一个child 获取到了theme 属性。

  再在themeSeclector 组件的最下面加一个反转,使用toArray()

{
/* map 和clone 后的children */}
{modChildren}
{
/* toArray(), 转化为数组,然后使用数组的reserse 方法进行反转 */}
{React.Children.toArray(this.props.children).reverse()}

  加一个p元素,使用count 方法,显示有children的个数

{React.Children.count(this.props.children)}

   还剩一个only, 只有一个children. 常用来判断children 是不是一个函数。如果我们children 需要用户提供一个函数的时候,它有可能提供多个元素,所以使用only 就会报错。如果themeSelect的组件是

{this.props.children()} , 使用{React.children.only(this.props.children)()}

  

  

转载于:https://www.cnblogs.com/SamWeb/p/11367778.html

你可能感兴趣的文章
关于eclipse maven引入第三方jar包后如何下载源代码
查看>>
no-sql数据库之redis
查看>>
关于浏览器内核的一些小知识,明明白白选浏览器!-
查看>>
2018年6月1日学习内容概要
查看>>
利用 Gearman 实现系统错误报警功能
查看>>
HDU 4035 期望dp
查看>>
bzoj 2301 莫比乌斯反演
查看>>
Tensor索引操作
查看>>
mongoose连表查询2
查看>>
html5 SVG
查看>>
.Net学习 第2季06 C#面向对象 Path类 File类 FileStream类 StreamReader/StreamWriter类
查看>>
VS2008+Qt 项目目录编辑配置
查看>>
【动态规划DP】传娃娃-C++
查看>>
LOJ.121.[离线可过]动态图连通性(线段树分治 按秩合并)
查看>>
201521123072 结对编程
查看>>
最长上升子序列
查看>>
maven 依赖、聚合和继承 (转)
查看>>
selinux介绍/状态查看/开启/关闭
查看>>
DockerAPI版本不匹配的问题
查看>>
Leetcode: Ugly Number II
查看>>