一、 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的更多相关文章

  1. React中props.children和React.Children的区别

    在React中,当涉及组件嵌套,在父组件中使用props.children把所有子组件显示出来.如下: function ParentComponent(props){ return ( <di ...

  2. react入门-props.children

    在ReactDOM.render里面我们写我们的自定义组件的时候有时需要加一下子元素进去: <!DOCTYPE html> <html lang="en"> ...

  3. React.js 小书 Lesson22 - props.children 和容器类组件

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson22 转载请注明出处,保留原文链接和作者信息. 有一类组件,充当了容器的作用,它定义了一种外层 ...

  4. React的this.props.children

    this.props用来获取组件从外部传入的属性,但是this.props.children比较特殊,它是由React给添加上的,表示组件的所有子节点.this.props.children可以用来读 ...

  5. react中对props.children进行操作

    之前写的更多的时候是直接使用简写 {props.children} 这样就可以了,但是当有时候需要对传入的子组件进行一些操作的时候需要用到React.Children方法 {React.Childre ...

  6. props.children 和容器类组件

    有一类组件,充当了容器的作用,它定义了一种外层结构形式,然后你可以往里面塞任意的内容.这种结构在实际当中非常常见,例如这种带卡片组件: 组件本身是一个不带任何内容的方形的容器,我可以在用这个组件的时候 ...

  7. React中的this.props.children

    React this.props.children this.props对象的属性与组件的属性一一对应,但是有一个例外,就是this.props.children属性.它表示组件的所有子节点. var ...

  8. 【JAVASCRIPT】React学习-巧用 props 的 children 属性实现内容填充

    背景 平常写组件,经常遇到需要获取内容放入组件内部的情形. 实现方法 我们有两种实现方式 1. 自定义 props render 的时候通过获取 this.props.content 填充到组件内部 ...

  9. [Recompose] Stream Props to React Children with RxJS

    You can decouple the parent stream Component from the mapped React Component by using props.children ...

随机推荐

  1. Linux 中查询 CPU 的核数的方法

    以一台 Linux 服务器为例.这台 Linux 包括两颗 Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz CPU, 单颗 CPU 包括 10 个 cpu core ...

  2. MaxCompute Spark开发指南

    0. 概述 本文档面向需要使用MaxCompute Spark进行开发的用户使用.本指南主要适用于具备有Spark开发经验的开发人员. MaxCompute Spark是MaxCompute提供的兼容 ...

  3. Handling Missing Values

    1) A Simple Option: Drop Columns with Missing Values 如果这些列具有有用信息(在未丢失的位置),则在删除列时,模型将失去对此信息的访问权限. 此外, ...

  4. CF981H K Paths

    CF981H K Paths 题解 一道不错的分治ntt题目 题目稍微转化一下,就是所有k条链的存在交,并且交的部分都被覆盖k次 所以一定是两个点,之间路径选择k次,然后端点两开花 f[x]表示x子树 ...

  5. LintCode 合并二维数组

    合并两个排序的整数数组A和B变成一个新的数组. 样例 给出A=[1,2,3,4],B=[2,4,5,6],返回 [1,2,2,3,4,4,5,6] 之前想的是用剑指offer里替换空格那种方法 但是把 ...

  6. MVC开发模式与web经典三层框架

    MVC:Model(模型)-View(视图)-Controller(控制器) ----是一种软件架构模式,一般把软件系统拆分为这三个层次. 视图View层:前端交互界面或者后端系统界面,它从模型中获取 ...

  7. iOS - CAReplicatorLayer 的运用

    http://www.cocoachina.com/ios/20151230/14822.html 序 CAReplicatorLayer可以复制自己子层的layer,并且复制的出来的layer和原来 ...

  8. 一文读懂JVM

    (一)JVM 基础知识 1)Java 是如何实现跨平台的? 注意:跨平台的是 Java 程序,而不是 JVM.JVM 是用 C/C++ 开发的,是编译后的机器码,不能跨平台,不同平台下需要安装不同版本 ...

  9. SSM+Maven+IDEA增删改查

    开发工具 IntelliJ IDEA Apache-tomcat-9.0 JDK 1.8 MySQL 8.0.11 Maven 3.5.4 IDEA+Maven搭建项目骨架 1. 新建Maven项目: ...

  10. LocalDateTime计算时间差

    LocalDateTime 为java8的新特性之一 LocalDateTime.now() 获得当前时间 java.time.Duration duration = java.time.Durati ...