React快速上手开发——Note

目录


 

  1. 下载和安装
  2. 第一个示例
  3. 创建最简单的组件
  4. 使用自己传入的props属性
  5. 设置props属性的类型检测,以及默认props属性值
  6. 使用state属性,设置事件监听器
  7. 使用子组件
  8. mixin
  9. 避免组件更新
  10. 使用PureRenderMixin
  11. 可以排序的表格

 

  

下载和安装

  版本: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>

  

posted @ 2018-05-02 10:59  寻觅beyond  阅读(1282)  评论(0)    收藏  举报
返回顶部