react的生命周期和组件

以下分享来自团队女童鞋yerr

三个状态

1.Mounted

React components被render解析生成对应的DOM节点,并在插入浏览器的DOM结构的一个过程;

getInitialState :初始化state
getDefaultProps : 初始化props

2. Update

一个mounted 的components被重新render的过程;(只有影响了DOM结构时才会被改变);

shouldComponentUpdate:组件在决定重新渲染(虚拟dom比对完毕生成最终的dom后)之前会调用该函数,该函数将是否重新渲染的权限交给了开发者,该函数默认直接返回true,表示默认直接出发dom更新;

componentWillReceiveProps:当节点初次被放入的时候componentWillReceiveProps并不会被触发。原因是因为 componentWillReceiveProps 经常会处理一些和old props 比较的逻辑,而且会在变化之前执行;不在组件即将渲染的时候触发,这也是这个方法设计的初衷。

3. Unmounted

一个mounted的RC对应的DOM节点被从DOM结构中移除的过程;
imagehttps://github.com/yerr1990/yerr1990.github.io/blob/master/images/lifecycle.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
var HelloMessage = React.createClass({
getInitialState:function(){ //在被render之前
alert("init");
return {
opacity: 0.5,
fontSize : '20px'
};
},
getDefaultProps:function () {//在被render之前
return {
name: "mary"
};
},
componentWillMount :function () {
alert("will");
},
render: function() {
return <h1 style={this.state}>Hello {this.props.name}</h1>; //这里也可以使用键值
},
componentDidMount:function () {
alert("did");
var _self = this;
window.setTimeout(function () {
_self.setState({
opacity: 1.,
fontSize : '50px'
})
},2000)
},
/*componentWillReceiveProps(nextProps) {
console.log("执行componentWillReceiveProps",nextProps);
}
*/
/* shouldComponentUpdate: function(nextProps, nextState) {
return true;
}*/
});
ReactDOM.render(
<HelloMessage name="john" />,
document.getElementById('example')
);

react 组件

React创建组件的三种方式及其区别

函数式定义的无状态组件

在大部分React代码中,大多数组件被写成无状态的组件,
通过简单组合可以构建成其他的组件等;这种通过多个
简单然后合并成一个大应用的设计模式被提倡。
特点:
1.不会被实例化,提高性能;
2.不能访问this对象;
3.没有生命周期;
4.只能访问props

es5原生方式React.createClass定义的组件

React.createClass会自绑定函数方法(不像React.Component只绑定需要关心的函数)导致不必要的性能开销,
增加代码过时的可能性。

es6形式的extendsReact.Component定义的组件

React.Component是以ES6的形式来创建react的组件的,
是React目前极为推荐的创建有状态组件的方式,最终会取代

组件api

设置状态:setState
替换状态:replaceState
设置属性setProps
替换属性replaceProps
强制更新:forceUpdate
获取DOM节点:findDOMNode
判断组件挂载状态:isMounted

接下来我们封装一个输出 “Hello World!” 的组件,组件名为 HelloMessage:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//您可能注意到,原生 HTML 元素名称是以小写字母开头的,而自定义 React 组件(类)名称是以大写字母开头的。
var HelloMessage = React.createClass({
render: function() {
return
<div className="content"> //className是js关键字
<h1>Hello World!</h1>
</div>
}
});
React.render(
<HelloMessage />,//组件名字
document.getElementById('example')//要插入的节点
);

注意,在添加属性时, class 属性需要写成 className ,for 属性需要写成 htmlFor ,这是因为 class 和 for 是 JavaScript 的保留字。

复合组件

我们可以通过创建多个组件来合成一个组件,即把组件的不同功能点进行分离。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
var WebSite = React.createClass({
render: function() {
return (
<div>
<Name name={this.props.name} />
<Link site={this.props.site} />
</div>
);
}
});
var Name = React.createClass({
render: function() {
return (
<h1>{this.props.name}</h1>
);
}
});
var Link = React.createClass({
render: function() {
return (
<a href={this.props.site}>
{this.props.site}
</a>
);
}
});
React.render(
<WebSite name="叶蓉蓉" site=" http://www.cnblogs.com/yerr1990" />,
document.getElementById('example')
);
1
2
3
4
5
6
7
8
9
React.render(
<div>
<MyLabel text={TextLabel} />
<MyTextfield />
<MyButton textlabel='OK' />
</div>,
document.getElementById('container')
);
//前面的 API 调用将组合的组件呈现到虚拟 DOM 中 ID 为 container 的 <div>— 元素中。

组件之间的通讯

【父组件】向【子组件】传值;
【子组件】向【父组件】传值;
没有任何嵌套关系的组件之间传值(PS:比如:兄弟组件之间传值)

1.【父组件】向【子组件】传值;

利用 props 来进行交流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 父组件
var MyContainer = React.createClass({
getInitialState: function () {
return {
checked: true
};
},
render: function() {
return (
<ToggleButton text="Toggle me" checked={this.state.checked} />
);
}
});
// 子组件
var ToggleButton = React.createClass({
render: function () {
// 从【父组件】获取的值
var checked = this.props.checked,
text = this.props.text;
return (
<label>{text}: <input type="checkbox" checked={checked} /></label>
);
}
});

但是呢,这里如果组件层层嵌套太深,那么从外到内组件的交流成本就变得很高

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 父组件
var MyContainer = React.createClass({
render: function() {
return (
<Intermediate text="where is my son?" />
);
}
});
// 子组件1:中间嵌套的组件
var Intermediate = React.createClass({
render: function () {
return (
<Child text={this.props.text} />
);
}
});
// 子组件2:子组件1的子组件
var Child = React.createClass({
render: function () {
return (
<span>{this.props.text}</span>
);
}
});

2【子组件】向【父组件】传值;

通过【子组件】控制自己的 state 然后告诉【父组件】的点击状态,然后在【父组件】中展示出来。因此,我们添加一个 change 事件来做交互。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// 父组件
var MyContainer = React.createClass({
getInitialState: function () {
return {
checked: false
};
},
onChildChanged: function (newState) {
this.setState({
checked: newState
});
},
render: function() {
var isChecked = this.state.checked ? 'yes' : 'no';
return (
<div>
<div>Are you checked: {isChecked}</div>
<ToggleButton text="Toggle me"
initialChecked={this.state.checked}
callbackParent={this.onChildChanged}
/>
</div>
);
}
});
// 子组件
var ToggleButton = React.createClass({
getInitialState: function () {
return {
checked: this.props.initialChecked
};
},
onTextChange: function () {
var newState = !this.state.checked;
this.setState({
checked: newState
});
// 这里要注意:setState 是一个异步方法,所以需要操作缓存的当前值
this.props.callbackParent(newState);
},
render: function () {
// 从【父组件】获取的值
var text = this.props.text;
// 组件自身的状态数据
var checked = this.state.checked;
return (
<label>{text}: <input type="checkbox" checked={checked} onChange={this.onTextChange} /></label>
);
}
});

3.没有任何嵌套关系的组件之间传值