一、 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. 【CodeVS】1083 Cantor表

    1083 Cantor表 1999年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题目描述 Description 现代数学的著名证明之 ...

  2. CURL POST PHP

    function SendPostCurl($url,$post_data){ $curl = curl_init(); //初始化 curl_setopt($curl, CURLOPT_URL, $ ...

  3. JDBC vs Hibernate(转)

    jdbc和Hibernate区别 刚开始学习JAVA时,认为Hibernate是一个很神圣的东西,好像是会了SSH,就能走遍全世界一样.记得曾经在枫叶面试的时候,我们几个同学出还说这个公司怎么这么的落 ...

  4. qt 鼠标拖动窗口放大缩小

    // 鼠标拖动 具体实现void mouseMoveEvent(QMouseEvent * pEvent) { if (pEvent->buttons() & Qt::LeftButto ...

  5. DELL(linux 系统里系统掉盘)(阵列Foreign)命令行里重做阵列

    故障现象 (阵列Foreign 系统下重做阵列) 例:四合一机器(DELL_XENCOMPA09) 有四个硬盘 如图 少认到一个 df  -h fdisk -l 2>/dev/null | gr ...

  6. 【JZOJ4745】【NOIP2016提高A组模拟9.3】看电影

    题目描述 听说NOIP2016大家都考得不错,于是CCF奖励省常中了 K 张变形金刚5的电影票奖励OI队的同学去看电影.可是省常中OI队的同学们共有 N(N >= K)人.于是机智的你想到了一个 ...

  7. Python 基于 NLP 的文本分类

    这是前一段时间在做的事情,有些python库需要python3.5以上,所以mac请先升级 brew安装以下就好,然后Preference(comm+',')->Project: Text-Cl ...

  8. day39-Spring 01-上次课内容回顾

  9. cloud-music

    非常感谢那些无私开源的程序员,希望我也能够有能力像你们那样,开源很多很有意思的东西~~ //index.html <!DOCTYPE html> <html> <head ...

  10. hdu4310 贪心

    考虑每次血口的要少 就按照一滴血多少伤害来计算.由于直接相除有小数.考虑x/y > a/b  =>  x*b >y*a; #include<stdio.h> #inclu ...