学习react的总结笔记

demo引入的库


<script type="text/javascript" src='../build/react.js'></script>
<script type="text/javascript" src='../build/react-dom.js'></script>
<script type="text/javascript" src='../build/browser.min.js'></script>

包括三个库,react.js核心库,react-dom.js提供与相关的功能,browser.js将jsx语法转javascript

初识

调用ReactDOM.render()方法,往里传入标签和要插入页面dom的两个参数


ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('example')
);

jsx语法

  • 对jsx的解析,遇到html标签就使用html规则进行解析,遇到代码块 { 就使用javascript进行解析;
  • 新建一个数组,在render函数第一个参数中传入以div包裹的代码块,代码块使用map遍历数组,对每个元素执行回调,返回封装的标签

var names = ['Alice', 'Emily', 'Kate'];
ReactDOM.render(
<div> {
    names.map(function (name) {
      return <div>Hello, {name}!</div>
    })
  }</div>,
  document.getElementById('example')
);

组件

  • 使用React.createClass()生成组件,传入一个对象参数,定义一个render方法,每个组件都又自己的一个render方法,返回并赋值给HelloMessage变量
  • 变量HelloMessage,首字母必须为大写否则出错,相当于类的命名,字母首个大写;
  • 传入React.DOM.render的参数一是以变量HelloMessage转为html格式传入,里面可定义html属性,在组件的render方法内可以使用this.props对象访问,render函数返回的标签只能包含一个顶层标签;
  • 在添加组件属性时,需注意class属性写成className,for属性写成htmlFor,因为class,for都是javascript的保留字;

var HelloMessage = React.createClass({
  render: function() {
    return <h1>Hello {this.props.name}</h1>;
  }
});

ReactDOM.render(
  <HelloMessage name="John" />,
  document.getElementById('example')
);

特例的属性this.props.children

  • React.Children为顶层Api之一,为处理this.props.children数据结构的工具,包括5个方法:map,count,forEach,toArray,only
  • this.props的属性与组件的属性一一对应,this.props.children属性例外,用于表示组件的所有子节点;
  • this.props.children的值有三种可能,子节点为0个,值为undefined;子节点为一个,值为object;子节点为多个,值为array;

//创建NodeList组件
var NodeList=React.createClass({
	//定义组件的render方法
	render:function(){
		//存储NodeList对象
		var self=this;
		console.log(React.Children);
		return (
			//顶层标签
			<ol>
				//代码块:使用React.Children.map遍历组件的所有子节点
				{
				React.Children.map(this.props.children,function(child){
					return <li>{self.props.greetting+" "}{child}</li>
				})}
			</ol>
		)
	}
});
ReactDOM.render(
	<NodeList greetting="hello">
		<span>item1</span>
		<span>item2</span>
		<span>item2</span>
	</NodeList>,
	document.getElementById('demo')
);

设置组件属性的类型PropTypes

组件的属性可以接受字符串,数值,对象,函数,使用PropTypes可以验证组件的属性的类型,当验证类型不通过时,会在控制台输出错误;


var Mytitle=React.createClass({
	propTypes:{
		title:React.PropTypes.string.isRequired,
	},
	render:function(){
		return <h1>{this.props.title}</h1>
	}
});
var data=123;
ReactDOM.render(
	<Mytitle title={data} />,
	document.getElementById('demo')
);

获取真实的DOM

  • 组件并不是真实的dom节点,只是存在内存中的一种虚拟的数据结构,叫做虚拟的DOM;
  • 在组件标识ref属性,在事件回调函数中通过this.refs.[refName]获取真实dom节点;
  • 由于this.refs.[refName]获取的时真实的dom,所以必须等到虚拟DOM插入文档后才能使用这个属性,否则报错;

var Mycomponet=React.createClass({
	handleClick:function(){
		//通过refs对象获取在组件标识的真实dom对象
		this.refs.realDom.focus();
	},
	render:function(){
		return (
			<div>
				//input中定义一个ref属性,方便回调函数获取真实dom
				<input type="text" ref="realDom" />
				<input type="button" value="按钮" onClick={this.handleClick} />			
			</div>
		);
	}
});
ReactDOM.render(
	<Mycomponet />,
	document.getElementById('demo')
);

this.state

  • 一个组件可相当一个状态机,有初始状态,当与用户交互时,导致状态发生改变,从而触发render,重新渲染;
  • this.getInitialState设置初始状态;this.state获取状态;this.setState修改状态,从触发render;
  • this.props与this.state都是描述组件的特性,区别是this.props描述的是定义就不改变的特性,this.state描述的是随用户交互而改变的特性

var LikeBtn=React.createClass({
	//设置初始的state,可通过this.state.[attr]获取状态
	getInitialState:function(){
		return {liked:false}
	},
	//单击事件,通过this.setState修改状态,状态改变自动调用render渲染组件
	handleClick:function(event){
		this.setState({liked:!this.state.liked});
	},
	render:function(){
	var text = this.state.liked ? 'like' : 'haven\'t liked';
	    return (
	      <p onClick={this.handleClick}>
	        You {text} this. Click to toggle.
	      </p>
	    );
	}
});
ReactDOM.render(
	<LikeBtn />,
	document.getElementById('demo')
);

表单中的特性

  • 通过表单与用户交互,在交互的过程中触发事件,改变组件状态,实时渲染组件UI
  • 定义一个输入文本框,监听change事件,当值改变时,通过事件改变组件状态,重新渲染组件

var Input=React.createClass({
	getInitialState:function(){
		return {value:'hello!'};
	},
	handleChange:function(event){
		//通过用户输入的值改变状态,进行渲染
		this.setState({value:event.target.value});
	},
	render:function(){
		var value=this.state.value;
		return(
			<div>
				//数据块两边不能加引号,自个调试容易犯的错 value="{value}"
				<input type="text" name="input" value={value} onChange={this.handleChange} />
				<p>{value}</p>
			</div>
		);
	}
});
ReactDOM.render(<Input />,document.getElementById('demo'));

组件的声明周期

  • 组件生命周期的状态包括:Mounting已经插入真实的dom;Updating正在被重新渲染;Unmounting已经移除真实Dom;
  • 每种状态提供两种处理函数,will进入状态前调用,did进入状态后调用;
  • 三种状态定义五个函数,componentWillMount,componentDidMount, componentWillUpdate,componentDidUpdate,componentWillUnmount
  • 两个特殊方法:componentWillReceiveProps(收到新参数调用),shouldComponentUpdate

var Input=React.createClass({
	getInitialState:function(){
		return {opacity:1.0};
	},
	//插入真实dom后执行
	componentDidMount:function(){
		var timer=setInterval(function(){
			var opacity=this.state.opacity;
			opacity=opacity-0.05;
			if(opacity<0.1){
				opacity=1.0;
			}
			//改变了state,重新渲染组件,接着往复执行componentDidMount
			this.setState({opacity:opacity});
		}.bind(this),100);
	},
	render:function(){
		var opacity=this.state.opacity;
		return(
			<div>
		//css样式为对象,第一个花括号为了jsx解析,第二个说明这事css对象
			<p style=>hello world!</p>
			</div>
		);
	}
});
ReactDOM.render(<Input />,document.getElementById('demo'));

参考资料

阮一峰 React 入门实例教程

Published: October 02 2016