props & children
一、 choosing the type at runtime
import React from 'react';
import { PhotoStory, VideoStory } from './stories'; const components = {
photo: PhotoStory,
video: VideoStory
}; function Story(props) {
// Wrong! JSX type can't be an expression.
return <components[props.storyType] story={props.story} />;
}
为了解决这个问题,我们将其赋值给首字母大写的变量
import React from 'react';
import { PhotoStory, VideoStory } from './stories'; const components = {
photo: PhotoStory,
video: VideoStory
}; function Story(props) {
// Correct! JSX type can be a capitalized variable.
const SpecificStory = components[props.storyType];
return <SpecificStory story={props.story} />;
}
二、 props in JSX
this.props引用属性,属性是不可以由组件自己进行修改,组件的属性是由父组件传递进来的。有多种方法指定JSX的props属性
2.1 键值对形式
<HelloWorld propName=propValue />
propValue可以是字符串,大括号包起来的数字或字符串{},大括号包起来的数组{[]},大括号包起来的一个变量,即时函数
1)JS表达式
可以传递任何大括号包裹的JS表达式作为props。
<MyComponent foo={1 + 2 + 3 + 4} />
对于MyComponent组件,props.foo属性等于10. if语句和for循环不是JS表达式,因此不能直接用于JSX。
2)字符串
可以传递一个字符串作为prop,因此下面的两条语句是等价的。
<MyComponent message="hello world" /> <MyComponent message={'hello world'} />
2.2 prop默认为true
下面两种表述是等价的
<MyTextBox autocomplete /> <MyTextBox autocomplete={true} />
2.3 defaultProps
可以通过指定defaultProps属性值来指定prop的默认值,这是用在未定义的props上,但是当props值为null时并不起作用:
class CustomButton extends React.Component {
// ...
} CustomButton.defaultProps = {
color: 'blue'
}; render() {
return <CustomButton /> ; // props.color will be set to blue
} render() {
return <CustomButton color={null} /> ; // props.color will remain null
}
class Greeting extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
} // Specifies the default values for props: 静态属性 类名.属性名
Greeting.defaultProps = {
name: 'Stranger'
}; // Renders "Hello, Stranger":
ReactDOM.render(
<Greeting />,
document.getElementById('example')
);
defaultProps用来确保当父组件没有提供值时,this.props.name仍然能够取到值,propTypes类型检测发生在defaultProps解析之后,所以类型检测也是适应于defaultProps.
2.3 扩展运算符
展开对象的形式,使用...+对象名,React自动看成是多个属性名
var props={
one:'123',
two:321
}
<HelloWorld {...props}/>
要经常使用解构赋值
class FancyCheckbox extends React.Component{
render() {
var { checked, title, ...other } = this.props;
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
return (
<label>
<input {...other}
checked={checked}
className={fancyClass}
type="checkbox"
/>
{fancyTitle}
</label>
);
}
});
三、children in JSX
在拥有开闭标签的JSX表达式中,开闭标签之间的内容传递给了props.children属性,你没办法通过 this.props.children
取得当前组件的子元素。 因为this.props.children
返回的是组件拥有者传递给你的 passed onto you 子节点。
class App extends React.Component{
componentDidMount() {
// This doesn't refer to the `span`s! It refers to the children between
// last line's `<App></App>`, which are undefined.
console.log(this.props.children);
} render() {
return <div><span/><span/></div>;
}
} ReactDOM.render(<App></App>, mountNode);
有多种不同的方法来传递children。
1)字符串
开闭标签之间可以是字符串,因此props.children就是这个字符串
<MyComponent>Hello world!</MyComponent>
在这里props.children=Hello world!
JSX会移除空格,因此下面的几种表述是等价的:
<div>Hello World</div> <div>
Hello World
</div> <div>
Hello
World
</div> <div> Hello World
</div>
2)JSX children
你也可以提供更多的JSX元素作为children,这在嵌套组件中很有用:
<MyContainer>
<MyFirstComponent />
<MySecondComponent />
</MyContainer>
你可以混合不同类型的children,因此你可以混合使用字符串和JSX children
<div>
Here is a list:
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
3)javascript children
可以使用任何大括号括起来的JS表达式作为children,比如下面这两种表述是相同的
<MyComponent>foo</MyComponent> <MyComponent>{'foo'}</MyComponent>
这通常用于呈现JSX任意长度列表,比如下面这种呈现一个HTML列表
function Item(props) {
return <li>{props.message}</li>;
} function TodoList() {
const todos = ['finish doc', 'submit pr', 'nag dan to review'];
return (
<ul>
{todos.map((message) => <Item key={message} message={message} />)}
</ul>
);
}
JS表达式还可以跟其他类型的children一起混用,这通常用于字符串模板
function Hello(props) {
return <div>Hello {props.addressee}!</div>;
}
4)函数
props.children可以传递任何数据,比如你有一个custom组件,你可以使用一个回调函数作为props.children.
function ListOfTenThings() {
return (
<Repeat numTimes={10}>
{(index) => <div key={index}>This is item {index} in the list</div>}
</Repeat>
);
} // Calls the children callback numTimes to produce a repeated component
function Repeat(props) {
let items = [];
for (let i = 0; i < props.numTimes; i++) {
items.push(props.children(i));
}
return <div>{items}</div>;
}
5)booleans,null,undefined are ignored
false,true,null,undefined都是合法的children,他们只是不渲染,下面这些表达式将渲染成同样的
<div /> <div></div> <div>{false}</div> <div>{null}</div> <div>{true}</div>
当需要有条件的渲染某个react组件时,这是很有用的,
<div>
{showHeader && <Header />}
<Content />
</div>
一些看起来像是false的值,比如说数字0,是会被React渲染的。比如下面这个例子,可能并不是你想象的结果,当props.message是一个空数组时,仍然会渲染:
<div>
{props.messages.length &&
<MessageList messages={props.messages} />
}
</div>
要解决这个问题,就要确保&&逻辑运算符前面的表达式是boolean:
<div>
{props.messages.length > 0 &&
<MessageList messages={props.messages} />
}
</div>
相反地,如果你需要在输出中输出false,true,null,undefined这些值,你需要将他们转化为字符串:
<div>
My JavaScript variable is {String(myVariable)}.
</div>
谨慎处理props.children
this.props.children的值有三种可能:如果当前组件没有子节点,他就是undefined;如果有一个子节点,数据类型是object;如果有多个子节点,数据类型就是array。所以处理this.props.children的时候要小心。
React提供了一个工具方法React.Children来处理this.props.children.
React.Children.map
我们可以用React.Children.map来遍历子节点,而不用担心this.props.children的数据类型是undefinde还是object.
React.Children.map(children, function[(thisArg)])
在每一个直接子级(包含在 children
参数中的)上调用 function
函数,此函数中的 this
指向 thisArg
。如果 children
是一个内嵌的对象或者数组,它将被遍历:不会传入容器对象到 function
中。如果 children 参数是 null
或者undefined
,那么返回 null
或者 undefined
而不是一个空对象。
<script type="text/jsx">
class NotesList extends React.Conponent{
render(){
return(
<ol>
{
React.Children.map(this.props.children,function(child){
return <li>{child}</li>;
})
}
</ol>
);
}
}
React.render(
<NotesList>
<span>hello</span>
<span>world</span>
</NotesList>,
document.getElementById('example')
);
</script>
React.Children.forEach
类似React.Children.map(),只是不会返回array
React.Children.forEach(children, function[(thisArg)])
React.Children.count
返回 children
当中的组件总数,和传递给 map
或者 forEach
的回调函数的调用次数一致。
React.Children.count(children)
React.Children.only
返回唯一的子节点,否则报错
React.Children.only(children)
React.Children.toArray
给子节点分配key值,转化为数组形式返回,这个方法在render中操作子节点集合是有用的,尤其是当你想要重新排列或者分割this.props.children时。
React.Children.toArray(children)
五、属性和状态对比
5.1 属性和状态的相似点
- 都是纯JS对象
- 都会触发render更新
- 都具有确定性,给定相同的属性和相同的状态,会有相同的结果
5.2 属性和状态的不同点
属性this.props | 状态this.state | |
能否从父组件获取初始值 | 能 | 否 |
能否由父组件修改 | 能 | 否 |
能否在组件内部设置默认值 | 能 | 能 |
能否在组件内部修改 | 否 | 能 |
能否设置子组件的初始值 | 能 | 否 |
能否修改子组件的值 | 能 | 否 |
状态就是和组件自己相关的,既不和父组件相关也不和子组件相关。
组件不能修改自己的属性,可以从父组件获得属性,父组件可以修改它的属性,他也可以修改子组件的属性。
由于this.props和this.state都用于描述组件的特性,可能会产生混淆。一个简单的区分方法是,
this.props 表示那些一旦定义,就不再改变的特性,而 this.state是会随着用户互动而产生变化的特性。
5.3 简单的区分
组件在运行时需要修改的数据就是状态。
比如:用户在表单填入的内容,属于用户跟组件的互动,所以不能用 this.props 读取.
文本输入框的值,不能用 this.props.value 读取,而要定义一个 onChange 事件的回调函数,通过 event.target.value 读取用户输入的值。textarea 元素、select元素、radio元素都属于这种情况
props & children的更多相关文章
- React中props.children和React.Children的区别
在React中,当涉及组件嵌套,在父组件中使用props.children把所有子组件显示出来.如下: function ParentComponent(props){ return ( <di ...
- react入门-props.children
在ReactDOM.render里面我们写我们的自定义组件的时候有时需要加一下子元素进去: <!DOCTYPE html> <html lang="en"> ...
- React.js 小书 Lesson22 - props.children 和容器类组件
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson22 转载请注明出处,保留原文链接和作者信息. 有一类组件,充当了容器的作用,它定义了一种外层 ...
- React的this.props.children
this.props用来获取组件从外部传入的属性,但是this.props.children比较特殊,它是由React给添加上的,表示组件的所有子节点.this.props.children可以用来读 ...
- react中对props.children进行操作
之前写的更多的时候是直接使用简写 {props.children} 这样就可以了,但是当有时候需要对传入的子组件进行一些操作的时候需要用到React.Children方法 {React.Childre ...
- props.children 和容器类组件
有一类组件,充当了容器的作用,它定义了一种外层结构形式,然后你可以往里面塞任意的内容.这种结构在实际当中非常常见,例如这种带卡片组件: 组件本身是一个不带任何内容的方形的容器,我可以在用这个组件的时候 ...
- React中的this.props.children
React this.props.children this.props对象的属性与组件的属性一一对应,但是有一个例外,就是this.props.children属性.它表示组件的所有子节点. var ...
- 【JAVASCRIPT】React学习-巧用 props 的 children 属性实现内容填充
背景 平常写组件,经常遇到需要获取内容放入组件内部的情形. 实现方法 我们有两种实现方式 1. 自定义 props render 的时候通过获取 this.props.content 填充到组件内部 ...
- [Recompose] Stream Props to React Children with RxJS
You can decouple the parent stream Component from the mapped React Component by using props.children ...
随机推荐
- Dijkstra,floyd,spfa三种最短路的区别和使用
这里不列举三种算法的实现细节,只是简单描述下思想,分析下异同 一 Dijkstra Dijkstra算法可以解决无负权图的最短路径问题,只能应付单源起点的情况,算法要求两个集合,开始所有点在第二个集合 ...
- Python 经典正则表达式语法实例
- 【arduino】anroid的app与arduino的ch05,进行蓝牙通信遇到的问题
Arduino程序上传不成功 显示系统找不到指定文件 错误信息显示是 avrdude: ser_open(): can't open device "\\.\COM1": 系统找不 ...
- Python之常用模块1
1.time datetime模块 #_*_coding:utf-8_*_ __author__ = 'Alex Li' import time # print(time.clock()) #返回处理 ...
- word Stock Market Indices
Stock Market Indices USA Africa Asia and Pacific Canada Europe Middle East South America Internation ...
- jquery.dataTables的探索之路-服务端分页配置
最近闲来无事想研究下数据表格,因为之前接触过layui和bootstrap的数据表格,本着能学多少学多少的学习态度,学习下dataTables的服务端分页配置.特与同学们一块分享下从中遇到的问题和解决 ...
- typora 使用
菜单 输入+换行键,产生标题,自动更新 [toc] [TOC] 段落 按换行键建立新的一行可在行尾插入打断线,禁止向后插入 按换行键建立新的一行<br/> 标题 开头#的个数表示,空格+文 ...
- Linux的登录和退出
Linux是一个多用户的操作系统,用户要使用该系统,首先必须登录系统,使用完系统后,必须退出系统. 本章主要讨论登录和退出系统的方法: 用户登录系统时,为了使系统能够识别自己,必须输入用户名和密码,经 ...
- 软件测试 → 第一章 基础-> 软件与软件危机
一. 软件概念 1.软件是计算机系统中与硬件相互依存的另一部分,它是包括程序,数据及其相关文档的完整集合.2.程序是按事先设计的功能和性能要求执行的指令序列.3.数据是使程序能正常操纵信息的数据结构. ...
- day40-Spring 01-上次课内容回顾