//ReactDOM.render(reactWhat,domWhere)在浏览器中渲染应用的一种途径
//React.DOM表示预约义好的HTML元素集合
//React.DOM.h1(attributes,children)表示一个预约义的React 组件
//h1()第一个参数接收一个对象,用于指定该组件的任何属性(好比id属性,三个特殊属性class:className,for:htmlFor,style:对象形式赋值)。
//h1()第二个参数定义了该组件的子元素(Hello world!)
//document.getElementById("app") 方法访问DOM 节点,告诉React 须要把应用渲染在页面的哪一个部分
ReactDOM.render(React.DOM.h1({
id: 'my-heading'
}, 'Hello world!'), document.getElementById('app'));
// JSX版本
ReactDOM.render(
<h1 id="my-heading" > <span><em>Hell < /em>o</span > world! < /h1>, document.getElementById('app') ); 复制代码
//自定义新组件
var Component = React.createClass({
//该对象须要包含一个名为render() 的方法来显示组件
render: function () {
//该方法必须返回一个React 组件,不能只返回文本内容。
return React.DOM.span(null, 'I\'m so custom');
}
});
//使用自定义组件
ReactDOM.render(
//React.createElement() 是建立组件“实例”的方法之一
React.createElement(Component),
//若是你想建立多个实例,还有另外一种途径,就是使用工厂方法:React.createFactory(Component);
document.getElementById('app')
);
复制代码
//自定义的组件能够接收属性,全部属性均可以经过this.props对象获取
var Component = React.createClass({
//propTypes是可选的,声明组件须要接收的属性列表及其对应类型
propTypes: {
//清晰地指明了name 属性是一个必须提供的字符串值
name: React.PropTypes.string.isRequired,
middleName: React.PropTypes.string,
},
//getDefaultProps() 方法返回一个对象,并为每一个可选属性(不带.isRequired的属性)提供了默认值。
getDefaultProps: function () {
return {
middleName: 'chris'
};
},
render: function () {
//请把this.props 视做只读属性。从父组件传递配置到子组件时,属性很是重要
return React.DOM.span(null, 'My name is ' + this.props.name);
}
});
ReactDOM.render(
React.createElement(Component, {
name: 'Bob'
}),
document.getElementById('app')
);
复制代码
var TextAreaCounter = React.createClass({
propTypes: {
text: React.PropTypes.string,
},
getDefaultProps: function () {
return {
text: '',
};
},
// 无状态版本
render: function () {
return React.DOM.div(null,
//文本框使用了defaultValue 属性,而不是你在常规HTML 中习惯使用的文本子元素
React.DOM.textarea({
defaultValue: this.props.text,
}),
React.DOM.h3(null, this.props.text.length)
);
},
// 有状态版本(状态state负责组件内部数据的维护)
_textChange: function (ev) {//数据发生改变时(即用户在文本框中输入内容时),组件能够经过一个事件监听器更新state
this.setState({//改变state 必须使用this.setState() 方法。该方法接收一个对象参数,并把对象与this.state 中已存在的数据进行合并
text: ev.target.value,
});
},
getInitialState: function () {//在初始化时,定义state中须要包含的属性,以保证能够经过this.state.text访问属性
return {
text: this.props.text,
};
},
render: function () {
return React.DOM.div(null,
//文本框使用了defaultValue 属性,而不是你在常规HTML 中习惯使用的文本子元素
React.DOM.textarea({
value: this.state.text,
//React 使用了合成事件来消除浏览器之间的不一致状况,React 在事件处理中使用驼峰法命名。
//当用户输入时触发。而不是像原生DOM 事件那样,在用户结束输入并把焦点从输入框移走时才触发。
onChange: this._textChange,
}),
React.DOM.h3(null, this.state.text.length)
);
}
});
// 使用自定义组件
ReactDOM.render(
React.createElement(TextAreaCounter, {
text: "Bob",
}),
document.getElementById("app")
);
复制代码
var myTextAreaCounter = ReactDOM.render(
React.createElement(TextAreaCounter, {
defaultValue: "Bob",
}),
document.getElementById("app")
);
//设置了新的state 值
myTextAreaCounter.setState({ text: "Hello outside world!" });
//获取了React 建立的父元素DOM 节点的引用
var reactAppNode = ReactDOM.findDOMNode(myTextAreaCounter);
//获取DOM 结构中首个<div id="app"> 节点。这也是你让React 进行渲染的位置:
reactAppNode.parentNode === document.getElementById('app'); // true
//访问组件的属性和状态
myTextAreaCounter.props; // Object { defaultValue: "Bob"}
myTextAreaCounter.state; // Object { text: "Hello outside world!"}
复制代码
//这个方法会接收新属性对象,让你能够根据新属性设置state
componentWillReceiveProps: function(newProps) {
this.setState({
text: newProps.defaultValue,
});
};
复制代码
设置默认的props
,也能够用dufaultProps
设置组件的默认属性. 对于组件类来讲只调用一次,该组件类的全部后续应用,getDefaultPops
将不会再被调用html
在使用es6
的class语法时是没有这个钩子函数的,能够直接在constructor
中定义this.state
。react
对于组件的每一个实例来讲,这个方法的调用有且只有一次,用来初始化每一个实例的 state
,在这个方法里,能够访问组件的 this.props
。es6
getInitialState
和 getDefaultPops
的调用是有区别的,getDefaultPops
是对于组件类来讲只调用一次,后续该类的应用都不会被调用, 而 getInitialState
是对于每一个组件实例来说都会调用,而且只调一次。算法
组件初始化以后,首次渲染以前调用,之后组件更新不调用,整个生命周期只调用一次,是在render
方法调用以前修改 state
的最后一次机会。canvas
react
最重要的步骤,建立虚拟dom
,进行diff
算法,更新dom
树都在此进行。此时就不能更改state
了。 该方法会建立一个虚拟DOM
,用来表示组件的输出。对于一个组件来说,render
方法是惟一一个必需的方法。浏览器
render
方法须要知足下面几点:性能优化
(1)只能经过 this.props
和 this.state
访问数据(不能修改)数据结构
(2)能够返回 null
,false
或者任何React
组件app
(3)只能出现一个顶级组件,不能返回一组元素dom
(4)不能改变组件的状态
(5)不能修改DOM
的输出
render
方法返回的结果并非真正的DOM
元素,而是一个虚拟的表现,相似于一个DOM tree
的结构的对象。react
之因此效率高,就是这个缘由。
组件渲染以后调用,只调用一次。 该方法被调用时,已经渲染出真实的 DOM
,能够再该方法中经过 this.getDOMNode()
访问到真实的 DOM
(推荐使用 ReactDOM.findDOMNode()
)。
因为组件并非真实的 DOM
节点,而是存在于内存之中的一种数据结构,叫作虚拟 DOM (virtual DOM)
。只有当它插入文档之后,才会变成真实的 DOM
。有时须要从组件获取真实 DOM
的节点,这时就要用到 ref
属性:
var Area = React.createClass({
render: function () {
this.getDOMNode(); //render调用时,组件未挂载,这里将报错
return <canvas ref='mainCanvas' > }, componentDidMount: function () { var canvas = this.refs.mainCanvas.getDOMNode(); //这是有效的,能够访问到 Canvas 节点 } }); 复制代码
须要注意的是,因为 this.refs.[refName]
属性获取的是真实 DOM
,因此必须等到虚拟 DOM
插入文档之后,才能使用这个属性,不然会报错。
此时组件已经渲染好而且用户能够与它进行交互,好比鼠标点击,手指点按,或者其它的一些事件,致使应用状态的改变,你将会看到下面的方法依次被调用
组件的 props
属性能够经过父组件来更改,这时,componentWillReceiveProps
未来被调用。能够在这个方法里更新 state
,以触发 render
方法从新渲染组件。
componentWillReceiveProps: function(nextProps) {
if (nextProps.checked !== undefined) {
this.setState({
checked: nextProps.checked
})
}
}
复制代码
react
性能优化很是重要的一环。 组件接受新的state
或者props
时调用,咱们能够在此对比先后两个props
和state
是否相同。 若是相同,则返回false
阻止更新,由于相同的属性状态必定会生成相同的dom
树,这样就不须要创造新的dom
树和旧的dom
树进行diff
算法对比,节省大量性能
若是你肯定组件的 props
或者state
的改变不须要从新渲染,能够经过在这个方法里经过返回 false
来阻止组件的从新渲染,返回 false
则不会执行 render
以及后面的 componentWillUpdate
,componentDidUpdate
方法。
该方法是非必须的,而且大多数状况下不会使用。
这个方法和 componentWillMount
相似,在组件接收到了新的 props
或者 state
即将进行从新渲染前,componentWillUpdate(object nextProps, object nextState)
会被调用。 注意此时能够修改state
,但最好不要在此方面里再去更新 props
或者 state
。
组件渲染
这个方法和 componentDidMount
相似,在组件从新被渲染以后,componentDidUpdate(object prevProps, object prevState)
会被调用。能够在这里访问并修改 DOM
。
组件将要卸载时调用,一些事件监听和定时器须要在此时清除。
// 组件卸载
React.unmountComponentAtNode(this.props.containerNode[0]);
复制代码