最近一个同事很急没有做任何交接就请了陪产假,然后我来维护。说实在的我一开始是一脸懵逼的。因为MV*项目里用的最多的还是Vue;React听说也了解过,但毕竟不熟。。。
不过不管如何这也是工作;同事也恭喜同事当爸了,打心理为他感到高兴!
代码down下来后开始查看的时候语法基本上使用的都是CMD,ES6还有本文讲的JSX,React组件。CMD,ES6这不难毕竟平常也经常用。但是JSX,React组件一开始就有点懵逼,
不过多看几遍加百度Google就懂了。
(好像废话有点多,好了,开始讲重点....)
首先是JSX:
我一开始看的时候,咦,怎么写dom不需要引号吗?后来才知道React发明了JSX利用html语法来创建虚拟dom。这同时也是React的核心之一。可以在内存中创建的虚拟DOM元素。React利用虚拟DOM来减少对实际DOM的操作从而提升性能。类似于真实的原生DOM,虚拟DOM也可以通过JavaScript来创建(React.createElement)
render(){ return React.createElement(‘div‘,null,‘content text‘) }
JSX本身就和XML语法类似,可以定义属性以及子元素。唯一特殊的是可以用大括号来加入;大括号中的语法就是纯JavaScript表达式,返回值会赋予组件的对应属性,因此可以使用任何JavaScript变量或者函数调用。同时大括号中使用JavaScript表达式来返回需要展现的元素。
JSX中的事件
JSX采用驼峰写法来描述事件名称,大括号中仍然是标准的JavaScript表达式,返回一个事件处理函数。在JSX中你不需要关心什么时机去移除事件绑定,因为React会在对应的真实DOM节点移除时就自动解除了事件绑定。且采用事件代理的模式:在根节点document上为每种事件添加唯一的Listener,然后通过事件的target找到真实的触发元素。这样从触发元素到顶层节点之间的所有节点如果有绑定这个事件,React都会触发对应的事件处理函数。这就是所谓的React模拟事件系统。尽管整个事件系统由React管理,但是其API和使用方法与原生事件一致。这种机制确保了跨浏览器的一致性:在所有浏览器(IE8及以上)都可以使用符合W3C标准的API,包括stopPropagation(),preventDefault()等等。对于事件的冒泡(bubble)和捕获(capture)模式也都完全支持
<button onClick={this.checkAndSubmit.bind(this)}>Submit</button>
在JSX中使用样式
在JSX中使用样式和真实的样式也很类似,通过style属性来定义,但和真实DOM不同的是,属性值不能是字符串而必须为对象,例如:
<div style={{color: ‘#ff0000‘, fontSize: ‘14px‘}}>Hello World.</div>
这段JSX中的大括号是双的,有点奇怪,但实际上里面的大括号只是标准的JavaScript对象表达式,外面的大括号是JSX的语法。所以,样式你也可以先赋值给一个变量,然后传进去,代码会更易读:
var style = { color: ‘#ff0000‘, fontSize: ‘14px‘ }; var node = <div style={style}>HelloWorld.</div>;
注意:在JSX中可以使用所有的的样式,基本上属性名的转换规范就是将其写成驼峰写法,例如“background-color”变为“backgroundColor”, “font-size”变为“fontSize”,这和标准的JavaScript操作DOM样式的API是一致的。
React自定义组件
首先看一个React官方的demo:
class HelloWorld extends React.Component{ render() { return ( <p> Hello, <input type="text" placeholder="Your name here" />! It is {this.props.date.toTimeString()} {/*通过this.props.data获取传过来的数据*/} </p> ); } }; setInterval(function() { React.render( <HelloWorld date={new Date()} />, document.getElementById(‘example‘) ); }, 500);
组件的概念和生命周期
React使用组件来封装界面模块,整个界面就是一个大组件,开发过程就是不断优化和拆分界面组件、构造整个组件树的过程。可以认为组件类似于其他框架中Widget(或Control)的概念,但又有所不同。React中的界面一切皆为组件,而Widget一般只是嵌入到界面中为完成某个功能的独立模块。如下图,整个页面是一个大的组件,然后再将其拆分成很多小的组件。组件机制加上JSX的语法,让你在构造界面时就像有一套符合项目需求的HTML标记,界面定义变得非常直观。
组件自身定义了一组props作为对外接口,每次props改变都能以整体刷新页面的思路去考虑界面展现逻辑。展示一个组件时只需要指定props作为XML节点的属性。组件很少需要对外公开方法,唯一的交互途径就是props。这使得使用组件就像使用函数一样简单,给定一个输入,组件给定一个界面输出。当给予的参数一定时,那么输出也是一定的。而传统控件通常提供很多方法让你在外部改变控件的状态和行为,当控件的状态在不同场景不同逻辑中可以被随意控制时,开发和调试也会变得复杂。
如果整个项目完全采用React,那么界面上就只有一个组件根节点;如果局部使用React,那么每个局部使用的部分都有一个根节点。在Render时,根节点由React.render函数去触发:
React.render( <App />, document.getElementById(‘react-root‘) );
而所有的子节点则都是通过父节点的render方法去构造的。每个组件都会有一个render方法,这个方法返回组件的实例,最终整个界面得到一个虚拟DOM树,再由React以最高效的方式展现在界面上。
除了props之外,组件还有一个很重要的概念:state。组件规范中定义了setState方法,每次调用时都会更新组件的状态,触发render方法。需要注意,render方法是被异步调用的,这可以保证同步的多个setState方法只会触发一次render,有利于提高性能。和props不同,state是组件的内部状态,除了初始化时可能由props来决定,之后就完全由组件自身去维护。在组件的整个生命周期中,React强烈不推荐去修改自身的props,因为这会破坏UI和Model的一致性,props只能够由使用者来决定。
对于自定义组件,唯一必须实现的方法就是render();除此之外,还有一些方法会在组件生命周期中被调用,如下图所示:
图中的方法几乎已经包括了React的所有API,自定义组件时根据需要在组件生命周期的不同阶段实现不同的逻辑。除了必须的render方法之外,其它常用的方法包括:
componentDidMount: 在组件第一次render之后调用,这时组件对应的DOM节点已被加入到浏览器。在这个方法里可以去实现一些初始化逻辑。
componentWillUnmount: 在DOM节点移除之后被调用,这里可以做一些相关的清理工作。
shouldComponentUpdate: 这是一个和性能非常相关的方法,在每一次render方法之前被调用。它提供了一个机会让你决定是否要对组件进行实际的render。
shouldComponentUpdate(nextProps, nextState) { return nextProps.id !== this.props.id; }
当此函数返回false时,组件就不会调用render方法从而避免了虚拟DOM的创建和内存中的Diff比较,从而有助于提高性能。当返回true时,则会进行正常的render的逻辑。
组件是React的核心,虽然功能很强大,但是其API和概念却十分简单,以至于你只要实现一个render方法就可以创建一个组件。这大大降低了React学习门槛。
参考及原文地址:http://www.infoq.com/cn/articles/react-jsx-and-component/