-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
全面解析children在react中的应用 #19
Labels
Comments
cool,只是有个问题,最后的图为什么三第二个元素被selected呢,可能是我漏看了一些内容? |
写得非常好!谢谢 |
很棒的总结 |
应该是代码没全放出来,肯定有个checked |
点个赞 |
1 similar comment
点个赞 |
# for free
to join this conversation on GitHub.
Already have an account?
# to comment
全面解析children在react中的应用
原文地址
react的核心是组件。你可以像嵌套html标签那样嵌套react组件,因为它类似于标记,使得编写jsx变得很容易。当我刚学react的时候,我认为使用
props.children
就是了。我认为自己知道关于children的一切。但是,我错了。因为我正在使用javascript,我可以改变children。我们可以给他们传递特殊的属性,来决定是否渲染他们并且可以按照我们的意愿去操作他们。让我们来深入发掘react中children的潜力吧子组件
我们假设有一个
<Grid/>
组件,它包含<Row/>
.你可以像下面这样使用:这三个Row组件是被当作props.children传递给Grid组件的。使用表达式容器(这是在JSX中那些歪歪的括号的技术术语),父容器可以渲染他们的孩子:
父亲也可以直接决定是否渲染孩子或者在渲染前操作他们。例如这个
<Fullstop/>
组件并不渲染任何孩子无论你想传递那个孩子给这个组件,它总是显示“Hello world”, 其他什么都不做。
一切都可以被当做子元素
在react中后代不一定都是组件,他们可以是任何东西。例如,我们可以传递给
<Grid/>组件一些文本作为它的后代,并且他也照常工作地很好。
(Live demo)
JSX将自动移除在一行收尾的空白以及空行。它还将字符串中文字的空白行压缩成一个空格。
这意味下面的例子将渲染出同样的东西:
你也可以混合多种类型的后代,同样也工作地很好:
(Live demo)
把函数作为子元素
我们可以传递任何javascript表达式作为子元素。这包括函数。
为了说明这是什么样子,这是一个组件,它执行一个传递给它的函数:
你可以像这样使用这个组件:
这个特殊的例子并没有什么用处,但是他展示了这个想法。
想象你不得不从服务器上抓取一些数据。你可以采用各种各样的方案,但是使用函数作为子元素是一种可行的模式:
花费一分钟玩一下这个demo, 并且看是否可以明白它如何工作。
不要担忧这超过你的理解范围。我想要的是,当你在野外看到这一切时,你并不感到惊讶。使用子元素,你可以做很多事情。
操纵子元素
如果你看react官方文档,你讲看到这句话“children are an opaque data structur”。他们基本告诉你props.children
可以是任何类型,例如数据,函数,对象,等等。因此你可以传递任何东西,你可以从不用关心他们。
React提供了一些操纵子元素的辅助方法,使用这些方法可以很简单无疼地操作子元素。这些方法在React.children下。
遍历子元素
React.children.map和React.children.forEach是两个最常用的辅助方法。他们像数组一样工作,除了他们是函数,对象或者其他东西的时候
这个<IgnoreFirstChild/>组件当map的时候,会忽略掉第一个,返回其他的
(Live demo)
下面这个例子,我们也可以使用this.props.children.map。但是如果一个人传递一个函数作为它的子元素,会发生什么呢? this.props.children将不是一个数组而是一个函数。我们会遇到错误。
![](https://camo.githubusercontent.com/2c3b90032eba078c4fa7167f4705e8cc9123dc781d3071da12f156177c087158/687474703a2f2f6d78737462722e626c6f672f696d672f72656163742d6368696c6472656e2d6572726f722e706e67)
使用React.Children.map函数,不会遇到任何问题:
统计子元素数量
因为this.props.children可能是任何类型,判断一个组件有多少个子元素将会是一件很困难的事。如果传递一个字符串或者函数作为子元素,那么将打破this.props.children.length的正常使用;
我们有一个后代,“Hello World”,但是.length相反却输出12!
那是为什么我们有React.Children.count:
不管子元素是什么类型它都可以准确地返回子元素的数量:
转化子元素为一个数组
作为最后的手段,上面没有任何方法适合你的需求,你可以使用React.Children.toArray转化你的子元素为数组. 如果你需要排序他们,这种手段是非常有用的。
以上的字符串渲染出排序后的字符串
(Live demo)
强制只有一个子元素
如果你回头看我们上面的<Executioner/>组件,它声明只有一个函数类型的子元素被传递进来。
我们可以使用propTypes来尝试限制它这样,代码如下:
这将使控制台输出一段信息,这些信息一部分会被开发者忽略掉,相反,我们可以使用React.Children.only在我们的render方法中!
这将返回在this.props.children中仅一个后代。如果有不只一个后代,它将扔出错误。把整个应用程序都磨成一个完美的程序,以避免懒惰的开发者试图破坏我们的组件。
修改子元素
我们可以将任意组件呈现为子元素,但是仍然从父类中控制它们而不是从我们渲染它们的组件中。为了证实这,我们假设有一个RadioGroup组件,它包含一组RadioButton组件(这个组件将渲染<input type="radio"在一个label标签中)。
这个RadioButton并不从RadioGroup这个组件中渲染,而是被当作一个子元素,这意味着在我们的程序中可以有这样的代码:
上面代码有一个问题。这个input并没有都在一个分组里,导致出现下面的现象
(Live demo)
为了把这些input标签放到同一个组里,需要他们有同样的name属性。我们当然可以遍历,然后给每一个单独的RadioButton分配一个name属性。
但那是一个乏味和错误的倾向。我们拥有所有javascript的力量。我们能不能用它来告诉我们的RadioGroup我们想让所有的子元素得到它的名字并且让它自动地处理它?
改变子元素的属性
在我们RadioGroup组件中,我们将增加一个绑定过的方法,叫renderChildren,在哪我们将编辑子元素的属性:
让我们开始遍历子元素,来得到每个独立的子元素:
我们如何可以编辑他们的属性呢?
不可变复制元素
这是今天最后一个辅助方法所起的作用。正如名字提示的,React.cloneElement复制一个元素。我们可以传递我们想复制的元素作为第一个参数 并且在第二个参数中传递我们想设置的属性:
这个cloned元素现在已经有了新属性new并被设置为'yes!'.
下面是我们完成RadioGroup的实际逻辑。我们复制每个元素,并设置复制生成的元素this.props.name:
最后一步是给我们的RadioGroup组件设置一个唯一name属性值:
总结
子元素让React组件感觉像标记,而不是脱节的实体。使用JavaScript的强大功能和一些Rect辅助函数,我们可以与它们一起创建声明性api,使我们的生活更轻松
The text was updated successfully, but these errors were encountered: