前言
随着前端技术的迅猛发展,各种前端框架也随势崛起,但归根结底,支撑每一款web框架流行的强大因素都是它能更好地服务于业务。React
自然也不例外,它的开发者当初正在开发Facebook的一个广告系统,由于不满足于当下任何的MVC
框架,所以就自己写了一套UI
框架,于是乎大名鼎鼎的React
就由此诞生了。React
的出现无疑为web
开发带来了颠覆性的改变,多少开发者夜以继日只为体验一把React
带来的快感。本文就将带领大家一起领略一番React
的理念、特色与情怀。
1. React不是一款MVC框架
我们首先要认清的事实就是,React
不同于我们之前常用的MVC
框架,如AngularJS
、Backbone
等,因为React
只专注于view
层(即MVC中的V)的表现,它是一个用于构建前端可复用UI
组件的库,同时,当数据发生变化时,React
会及时有效地更新和渲染相应的组件。对于越来越复杂的前端界面,尤其是对于数据不断变化的web应用,React
实现了将变化的数据高效无误的反映在页面上。
下面摘一句React官方doc中的一句话:
We built React to solve one problem: building large applications with data that changes over time.
2. 使用JSX取代HTML模板
JSX
是React
的核心概念之一,JSX
并不是一种新语言,它是对JavaScript
语言的扩展,但并没有改变JavaScript
的语法,看起来很像XML
。JSX
使用基于XML
的方式表达组件的嵌套,保持和HTML
一致的结构,语法上除了在描述组件上比较特别以外,其它基本和Javascript
保持一致。 并且最终React
会把所有的JSX
都编译为JS
。
我们先来看一个小例子:
var element = <div className="title"> <h1>Hello World</h1> </div>; ReactDOM.render(element,document.body);
从该例子可以看出,React
实现了直接将HTML
嵌入到JavaScript
中的能力,相信很大一部分人刚接触JSX
这种语法时,都心存怀疑,因为多少年我们一直强调MVC
,即表现层与逻辑层是要分离的,我们使用HTML
模板的目的也是为了避免表现层与逻辑层的耦合。但React
使用JSX
的这种设计思想,仿佛让我们一夜回到解放前。使用JSX
的好处到底是什么呢?
其实,我们最初使用HTML
模板的目的是让表现层更加独立,这样对HTML
的修改就变得更加简单,不需要去看逻辑代码。但如今,web应用已经变得越来越复杂,模板对应的逻辑层代码也是严重依赖于模板DOM
结构,这就造成了表现层与逻辑层的严重耦合,最初不看逻辑而简单修改界面的想法也打破了。换句话说,表现层和逻辑层还是互不可分的。而且,为了模板与逻辑的良好合作,还不得不引入很多新概念。我们拿AngularJS
举例,使用AngularJS
确实从结构上分离了表现层与逻辑层,但是HTML
里却混入了大量的标记属性,而且,初学者如果不懂AnjularJS
的语法,根本不明白HTML
中标记属性的寓意何在,由此学习难度与成本也大幅度提升。
说到这儿,我们大概就能体会到React
使用JSX
的独到之处了。JSX
除了使用XML
标记的方式去直接声明界面以外,并没有增加其它未知的语法与标记,这不但降低了学习成本,让初学者更快地上手使用React
,而且使写出的代码可读性更高,更易于理解。
另外,虽然React
推荐使用JSX
,但并不是必须的,我们也可以完全使用JavaScript
进行开发,但JSX
在定义类似HTML
的树形结构时,非常简洁明了,下面的例子是不使用JSX
和使用JSX
开发的对比:
#不使用JSX,重复调用React.createElement方法 React.render( React.createElement('div',null,React.createElement('div','Hello World') ) ),document.body ); #使用JSX,简洁明了的类似HTML树形结构 React.render( <div> <div> <div>Hello World</div> </div> </div>,document.body );
所以,有JSX
这种好东西,我们有什么理由不用呢?
3. 一切皆组件
组件,即被独立封装的可复用UI
部件。组件也是React
的核心思想之一。React
让我们重新规划界面,把任何一个功能独立的模块都定义成组件。一个个的组件通过不断复用,组合与嵌套等,构成一套完整的UI
界面。所以说,使用React
开发的界面一切皆为组件。
组件的概念并不难理解,最重要的还是组件之间的交互。React
为每个组件都提供一个render
方法,这个方法返回组件的实例。组件有两个重要的概念:props
和state
,他们的作用都是用于描述组件的状态。props
是组件对外交互的接口,是一种父级向子级传递数据的方式;state
用于记录组件的不同状态,React
把组件看成是一个状态机,通过与用户的交互,实现不同状态,然后重新渲染组件,让UI界面及时有效地随数据变化而变化。
以下是在组件中使用state
和props
的应用实例。我们可以在父组件中设置state
,并通过在子组件上使用props
将其传递到子组件上。
var MainCom = React.createClass({ getInitialState: function() { return { message: "Learn React",link: "https://facebook.github.io/react/" }; },render: function() { return ( <div> <Message message={this.state.message} /> <Link link={this.state.link} /> </div> ); } }); var Message = React.createClass({ render: function() { return ( <h1>{this.props.message}</h1> ); } }); var Link = React.createClass({ render: function() { return ( <a href={this.props.link}> {this.props.link} </a> ); } }); ReactDOM.render( <MainCom />,document.getElementById('main-container') );
组件化的方式带来了UI
功能模块之间的分离。对于MVC
开发模式来说,开发者将实现表现层,数据层,控制层的分离。对于React
而言,则完全是一个新的思路,开发者从功能的角度出发,将UI界面分成不同的组件,每个组件都独立封装。
4. 虚拟DOM提升性能
传统的web开发中,我们通常使用JS
或jQuery
操作DOM的方式将不断变化的数据实时地反映到页面上,随着页面逻辑复杂度的提升,频繁大量的DOM操作往往会造成网站性能较低,代码也变得越来越难维护。即使使用了MVC
框架来重新架构代码,但也没有办法减少你所维护的状态,也就是说没有办法减少DOM操作。
后来又出现了MVVM
模式,通过视图模板和状态的双向绑定,双向绑定引擎就会在状态更新的时候自动更新视图。MVVM
模式很大程度的减少了视图更新的逻辑,即减少了DOM操作。但这种方法也是存在问题的,每次状态发生变化时,模板引擎都会重新渲染整个视图,即用新的视图替换掉旧的视图。我们知道,这样做是影响性能的,因为即使一处小小的修改都会引起重新渲染DOM。
在React
的思想里,是完全不需要操作DOM的。React
提出了新概念,即虚拟DOM
。使用React
进行开发时,所有的DOM构造都是通过虚拟DOM
进行的,每当数据发生变化时,React
都会重新构造DOM树,然后将新构造的DOM树与上一次的DOM树进行对比(这就用到了React的DOM Diff算法
),得到两者之间的差异后,仅需将变化的DOM部分进行更新。由于每次生成虚拟DOM都很快,DOM Diff算法
找出两个DOM树之间的差异也很快(时间复杂度O(n)
),所以跟传统的操作DOM相比,使用虚拟DOM
的方法在速度和性能上的优势是十分明显的。
我们举一个简单的例子,假设我们有一个list如下:
<ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul>
现在想把它更新成:
<ul> <li>6</li> <li>7</li> <li>8</li> <li>9</li> <li>10</li> </ul>
我们传统的做法是先删除1,2,3,4这些节点,然后再追加6,7,8,9,10这几个新节点,这就意味这会有4次删除操作和5次添加操作。但React会把旧的和新的DOM树做一下Diff,然后发现其实不用删除1,2,3,4节点,而是可以直接修改这四个节点的innerHTML为6,7,8,9,然后再追加一个节点10就可以了。这样就比9次节点DOM操作快多了。
5. 总结
本文只是个人对React的设计思想的一些浅显的认识,写的比较零散,当然React的优点还有很多的,还待大家去慢慢学习与体会。当然,事物都有相对性,在实际的开发过程中,还是要挑选最适合的框架,而不是盲目从众。