React快速上手开发——Note
目录
- 下载和安装
- 第一个示例
- 创建最简单的组件
- 使用自己传入的props属性
- 设置props属性的类型检测,以及默认props属性值
- 使用state属性,设置事件监听器
- 使用子组件
- mixin
- 避免组件更新
- 使用PureRenderMixin
- 可以排序的表格
下载和安装
版本:14.7 比较老的一个版本
下载地址如下:https://github.com/facebook/react/archive/v0.14.7.tar.gz
可以使用wget或者curl命令下载
第一个示例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>First Test React</title>
<script src="react/build/react.js"></script>
<script src="react/build/react-dom.js"></script>
</head>
<body>
<div id="app"></div>
</body>
<script>
ReactDOM.render(
React.DOM.p(
{
style : {
color:"red",
fontSize:"30px"
},
name : "demo",
className : "test",
},
"hello world ",
React.DOM.em(null, "this is react")
),
document.getElementById("app")
);
</script>
</html>
ReactDOM对象的render方法,会进行“渲染”操作
render方法接收3个参数:
第1个参数是组件(Component)
第2个参数是容器(Container),表示要将组件放到哪里,一般是一个document.getElementXXX选定的一个元素
第3个参数是callback函数,初学的时候可以省略。
关于render方法中第一个参数:组件,可以使用React.DOM.* (),后面的*是元素的tag名称(可以认为是组件),比如p、h1、h2、textarea....可以接受多个参数,
第1个参数是一个json格式的对象,包含这个元素(组件)的属性信息,比如上面的color,fontSize等style信息,以及name,以及class;
之后可以是多个字符串,或者也可以是多个组件(形成了嵌套组件),甚至是组件和字符串的组合。
关于render方法第二个参数:容器,可以使用document.getElementById或者其他几个获取元素节点的语句。
运行结果如下:

创建最简单的组件
首先,创建组件是使用React.createClass({ }),接收一个json格式的对象,该对象必须有一个render方法,返回一个组件。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>First Test React</title>
<script src="react/build/react.js"></script>
<script src="react/build/react-dom.js"></script>
<style>
.test {font-size:30px;}
</style>
</head>
<body>
<div id="app"></div>
</body>
<script>
var myComponent = React.createClass({
//每一个组件必须有一个render方法
render : function() {
return React.DOM.div(
{
//设置style属性
style : {
color : "red"
},
//设置class
className : "test",
id : "123"
},
"hello world ",
React.DOM.span(null, "this is react")
);
}
});
ReactDOM.render(
React.createElement(myComponent),
document.getElementById("app")
);
</script>
</html>
运行结果如下:

这个例子中,span标签中的内容都是在创建组件的时候写死的,真正的开发中,这样显然是不适用的,所以react提供了props和state两个属性,后面会介绍怎么使用。
使用自己传入的props属性
<script>
var myComponent = React.createClass({
//每一个组件必须有一个render方法
render : function() {
return React.DOM.div(null,
//尝试使用自己传入的MyData属性
this.props.MyData,
React.DOM.div(null, this.props.MyData.length)
);
}
});
ReactDOM.render(
React.createElement(
myComponent,
{MyData : "hello react"}
),
document.getElementById("app")
);
</script>
运行结果:

在创建组件的时候,使用this.props.*来使用props属性,此时的this指的是当前的组件。
而在传入props属性的时候,是在React.createElement(component, { props } )的第二个参数中传入一个json对象格式的值,表示传递给组件的props属性和值。
最好将props属性是做只读属性,不要去修改props的属性。
设置props属性的类型检测,以及默认props属性值
<script>
var myComponent = React.createClass({
//每一个组件必须有一个render方法
render : function() {
return React.DOM.div(null,
//尝试使用自己传入的MyData属性
this.props.MyData,
React.DOM.div(null, this.props.Age)
);
},
//设置prop属性类型检测
propTypes : {
//要求prop属性中的MyData类型为string,并且不可缺少
MyData : React.PropTypes.string.isRequired,
//要求prop属性中的MyData类型为string,可以缺少
Age : React.PropTypes.number
},
//设置prop属性的默认值
getDefaultProps : function() {
return {
//Age属性在未传入时,就是用这里设置的默认值99
Age : 99
}
}
});
ReactDOM.render(
React.createElement(
myComponent,
//注意这里只传入了MyData属性,所以组件中的Age属性会使用默认值99
{MyData : "hello react"}
),
document.getElementById("app")
);
</script>
运行结果如下:

使用state属性,设置事件监听器
<script>
var TextAreaCount = React.createClass({
render : function() {
return React.DOM.div(null,
React.DOM.textarea({
value : this.state.text,
onChange : this._textChange //绑定事件处理程序
}),
React.DOM.h3(null, this.state.text.length)
);
},
//事件处理程序,修改state的text属性值
_textChange : function(ev) {
this.setState({
text : ev.target.value
});
},
//从props属性中获取属性值,赋值给state
getInitialState : function() {
return {
text : this.props.defaultText
}
}
});
ReactDOM.render(
React.createElement(TextAreaCount, {defaultText: "hello"}),
document.getElementById("app")
);
</script>
运行结果如下:每次修改textarea中的值时,下方的数字(长度)就会变化


这段代码中,需要注意的是:getInitialState方法,是为了将外部传给props的text属性,交给state的text属性。否则组件中访问text是不存在的,就会报错。
使用子组件
<script>
//子组件
var Counter = React.createClass({
name : "Counter",
propTypes : {
count : React.PropTypes.number.isRequired
},
render : function() {
return React.DOM.span(null, this.props.count);
}
});
//父组件
var TextAreaCount = React.createClass({
//从props属性中获取属性值,赋值给state
getInitialState : function() {
return {
text : this.props.defaultText
}
},
render : function() {
var counter = null;
if (this.state.text.length > 0) {
counter = React.DOM.h3(null,
React.createElement(Counter, {count : this.state.text.length})
);
}
return React.DOM.div(null,
React.DOM.textarea({
value : this.state.text,
onChange : this._textChange
}),
//React.DOM.h3(null, this.state.text.length)
counter
);
},
//事件处理程序,修改state的text属性值
_textChange : function(ev) {
this.setState({
text : ev.target.value
});
},
});
ReactDOM.render(
React.createElement(TextAreaCount, {defaultText: "hello"}),
document.getElementById("app")
);
</script>
注意两个组件的声明周期。
mixin
避免组件更新
在某个组件中实现shouldComponentUpdate(nextProps, nextState_ignore),根据nextProps中某个属性是否改变,来决定是否重新渲染组件。
//子组件
var Counter = React.createClass({
name : "Counter",
propTypes : {
count : React.PropTypes.number.isRequired
},
render : function() {
//打印渲染操作
console.log(this.name + "::render()");
return React.DOM.span(null, this.props.count);
},
shouldComponentUpdate : function(nextProps, nextState_ignore) {
return nextProps.count !== this.props.count;
}
});
//父组件
var TextAreaCount = React.createClass({
//从props属性中获取属性值,赋值给state
getInitialState : function() {
return {
text : this.props.defaultText
}
},
render : function() {
//打印渲染操作
console.log(this.name + "::render()");
var counter = null;
if (this.state.text.length > 3) {
counter = React.DOM.h3(null,
React.createElement(Counter, {count : this.state.text.length})
);
}
return React.DOM.div(null,
React.DOM.textarea({
value : this.state.text,
onChange : this._textChange
}),
//React.DOM.h3(null, this.state.text.length)
counter
);
},
//事件处理程序,修改state的text属性值
_textChange : function(ev) {
this.setState({
text : ev.target.value
});
},
});
ReactDOM.render(
React.createElement(TextAreaCount, {defaultText: "hello"}),
document.getElementById("app")
);
</script>
在没有重写Counter组件的shouldComponentUpdate方法时,即使文本框中的文本长度是否改变,只要内容发生改变,Counter组件就要重新渲染一次。假设最初有5个字符,然后将这5个字符拷贝一下,然后粘贴,虽然进行了操作,但是长度仍旧是5个字符,那么Counter组件就没有必要再进行渲染一次了,所以此时判断props中的count是否改变,来决定是否要更新组件
使用PureRenderMixin
向上面这样,为了减少组件的更新,那么就需要在多个组件中重写shouldComponetUpdate,对于每一个属性,都要增加判断,这样做所花费的时间反而比更新组件花的时间要多,有点本末倒置了。
React里面提供了一个插件,PureRenderMixin,包含在react-with-addons.js中,所以要将react.js换位react-with-addons.js。
这样的话,只需要在组件中添加一个mixin即可。
比如在重构上面这个代码中Counter组件:
<script src="react/build/react-with-addons.js"></script>
<script src="react/build/react-dom.js"></script>
<script>
//子组件
var Counter = React.createClass({
name : "Counter",
mixins :[React.addons.PureRenderMixin], // 有了PureRenderMixin,就可以省略shouldComponentUpdate了
propTypes : {
count : React.PropTypes.number.isRequired
},
render : function() {
//打印渲染操作
console.log(this.name + "::render()");
return React.DOM.span(null, this.props.count);
}
});
。。。。。。。。。
</script>
可以排序的表格
<script>
var header = ["Book", "Author", "Language", "Publishd", "Sales"];
var data = [
["The Lord of the Rings", "J. R. R.Tolkien", "English", "1954-1955", "150 million"],
["Le Ptit Prince", "Antonie de Saint-Exupery", "French", "1943", "140 million"],
["Harry Potter and the Philosopher", "J. K. Rowling", "English", "1997", "107 million"],
["And Then There Were None", "Agatha Christie", "English", "1939", "100 million"],
["Dream of the red chamber", "Cao Xueqin", "Chinese", "1754-1791", "100 million"],
["The Hobbit", "J. R. R Tolkien", "English", "1937", "100 million"],
["She A History of Adventure", "H. Rider Haggard", "English", "1887", "100 million"]
];
var Excel = React.createClass({
displayName :"Excel",
render :function() {
return (
React.DOM.table(null,
React.DOM.thead({onClick : this._sort},
React.DOM.tr(null,
this.state.headers.map(function(title, id){
return React.DOM.th({key: id}, title);
})
)
),
React.DOM.tbody(null,
this.state.data.map(function(row, index){
return (
React.DOM.tr({key:index}, row.map(function(field, id){
return React.DOM.td({key:id}, field);
}))
);
})
)
)
)
},
_sort : function(ev){
var column = ev.target.cellIndex;
var data_bk = this.state.data.slice(); //不要直接更改state,先复制state中的数据,再使用setState修改
data_bk.sort(function(a, b){
return a[column] > b[column] ? 1 : -1;
});
this.setState({
data : data_bk
});
},
getInitialState :function (){
return {
headers : this.props.headers,
data : this.props.initialData
}
}
});
ReactDOM.render(
React.createElement(Excel, {headers : header, initialData : data}),
document.getElementById("app")
);
</script>
浙公网安备 33010602011771号