react的特点
- 简单
- 申明式
react的核心是组件,组件的设计目的是提高代码复用率、降低测试难度和代码复杂度。
提高代码复用率:组件将数据于逻辑进行封装,类似于类。
降低测试难度:组件高内聚低耦合,很容易对单个组件进行测试。
降低代码复杂度:直观的语法,极大的提高可读性。
JSX
Javascript XML简称JSX,官方的解释是一种ECMAScript的特性,并不是一种语言。开发React应用可以使用JSX也可以不使用。下面给出一个dom,大概有设计到一些JSX的简单应用。
<script type="text/babel">
var style = {
border: "1px solid black",
color: "red"
}
var rawHTML = {
__html: "<h3>dangerouslySetInerHTML</h3>"
}
var Helloword = React.createClass({
getProp: function(){
if (this.props.name) {
return this.props.name;
}else{
return 'fuck';
};
},
render: function () {
return (<p className="ps" style={style}>
Hello , {this.props.name ? this.props.name : "fuck"} <br/>
Hello , {this.props.title ? this.props.title : 'kitty'} <br/>
Hello , {this.props.hobby || 'huazi'}
</p>)
}
})
ReactDOM.render(<Helloword
name="react-0.14.7"
hobby='sun'
title="bitch" />,
document.getElementById('container'));
ReactDOM.render(<div
dangerouslySetInnerHTML={rawHTML}></div>,
document.getElementById('dangerous'));
</script>
上面代码需要正确的引用react.js和react-dom.js以及browser.js才能正常执行。本文写作日期最新的react.js是0.14.7。于之前的版本语法会有所不同,比如script标签的type属性还有些API都有差异。鉴于react第一个大版本还没发布,姑且先按照最新的API 来参考啦。
代码中需要注意的是自定义标签HelloWrold的首字母必须是大写,以此来和原生标签区分。另外dangerouslySetInnerHTML是react的非dom属性,另外还有ref和key。另外,{}对应的求值表达式也是个需要注意的点。至此,hello react已经完成。
React组件的生命周期
粗略的可以分为三大块:初始化、运行中、销毁。其中三大块生命周期中React有提供一些钩子函数来帮助开发者控制整个生命周期!
-
初始化
getDefaultProps: 只调用一次,实例之间共享引用。
getInitialState: 初始化每个实例的特有状态。
componentWillMount: 组件将被加载,render之前最后一次修改状态的机会。
render: 只能访问this.props和this.state,只有一个顶层组件,不允许修改dom输出和状态
componentDidMount: render完毕,可以修改dom。
需要注意的是getInitialState返回值必须是空或者对象,另外reactDOM.render调用之前就会触发getDefaultProps,或者说在createClass时就触发了。
<script type="text/babel">
var count = 1;
var style = {
border: "1px solid black",
color: "red"
}
var Helloword = React.createClass({
getDefaultProps: function(){
return {name: 'huazi'}
},
getInitialState: function(){
return {mess:false,ready: 'now = '+count++};
},
componentWillMount: function(){
this.setState({
mess: true
})
},
render: function () {
return (<p className="ps" style={style}>
Hello , {this.props.name} <br/>
hello , {this.state.ready+ ''} <br/>
hello , {this.state.mess+ ''}
</p>)
},
componentDidMount: function(){
ReactDOM.findDOMNode(this).innerHTML += "<h1>ohh</h1>";
}
})
ReactDOM.render(<div><Helloword></Helloword><Helloword></Helloword></div>,
document.getElementById('container'));
</script>
对照例子和上述的对应生命周期,可以比较直观的理解初始化阶段的钩子们。
-
运行中
componentWillReceiveProps: 父组件在修改属性时触发,可以修改新属性、修改状态
shouldComponentUpdate: 返回false会阻止render调用,谨慎使用
componentWillUpdate: 组件被更新之前触发,不能修改状态和属性
render: 只能访问this.props和this.state,只有一个顶层组件,不允许修改dom输出和状态
componentDidUpdate: 组件被更新完毕,可以修改dom
上边的代码中HelloWorld是HelloComp的子组件,HelloComp中的逻辑就是包含子组件HelloWorld,子组件的name属性时父组建的state.name。触发input的onChange事件的时候,调用handleChange修改当前组件的state.name的值为输入值。同时会修改子组件的name属性值。这时候就是在运行中状态修改了组件的state。依次会执行代码中的三个钩子。
-
组件销毁
componentWillUnmount: 在删除组件之前做一些清理操作,比如解绑事件清除计时器。
父组建没有引用子组件就会触发销毁子组件,子组件的钩子就会执行。当销毁挂在一个标签上的组件时使用的是React.unmountComponentAtNode,这时会首先销毁父组建然后销毁子组件。