React框架为什么这么火:React的设计思想

原文链接:http://mp.weixin.qq.com/s?__biz=MzA5Njc3Njk5NA==&mid=2650528748&idx=1&sn=4d3093e963ce76c642eb0c5d9a97625b#rd

React的起源

React来自于Facebook,是的,就是那个你们听说过但是打不开的网站。Facebook的开发者当时在开发一个广告系统,因为对当前所有的MVC框架不满意,所以就自己写了一个UI框架,于是就有了React。后来因为觉得实在是好用,所以在2013年月份开源的此框架。经过这几年的沉淀,React越来越强大,也受到了越来越多的开发者喜爱。React目前(2015-05-04)的版本是0.14.0,从版本号上看还没有达到1.0版,意味着React还在频繁地修改,普遍应用于产品中还需要一定的时间。2015年三月份的F8开发者大会上,Facebook又发布了React Native,正式把React的触角伸向了APP。同时还为React native开发了一款基于Atom的IDE-Nuclide,也是开源。

React来势汹汹,大有一统江湖的气势。前端开发者应该保持学习新技术的热情,很有必要熟悉React相关技术。下面我们简要谈谈React相关的技术。

React的设计思想

熟悉一个新技术的关键是熟悉他的特色和理念

React框架本身和我们常用的JavaScript MVC框架,如:AngularJS,Backbone,Ember等,没有直接的可比性。在React的官方博客中明确阐述了React不是一个MVC框架,而是一个用于构建组件化UI的库,是一个前端界面开发工具。所以顶多算是MVC中的V(view)。React并没有重复造轮子,而是有很多颠覆性的创新,具体的特性如下:

编写简单直观的代码

在年初的React开发者大会上,React的项目经理Tom Occhino讲述了React的最大的价值,React最大的价值不是高性能的虚拟DOM、封装的事件机制、服务器端渲染,而是声明式的直观的编码方式。React号称能让新人第一天开始使用就能开发新功能。简单的编码方式会让新手能很快地上手,同时也降低了代码维护的成本。这一特性决定了React能快速引起开发者的兴趣并广泛传播的基础。以下是React基于这一理念的具体做法。

简化可复用的组件

React构建UI是使用组件化的方式,而不是常见的模板。组件并不是一个新概念,它是某个独立功能或者界面的封装,达到复用或者UI和业务松耦合的目的。

组件化的设计理念也出现了很多年了,我们常用的ExtJS、YUI、jQueryUI、BootStrap等等都会提供大量的可复用的UI组件。比如在Bootstrap中使用对话框组件:

// 初始化
$(‘#myModal‘).modal({
    keyboard: false
});

// 显示
$(‘#myModal‘).modal(‘show‘);

// 关闭事件
$(‘#myModal‘).on(‘hidden.bs.modal‘, function (e) {
  // do something...
});

可以看到我们常用的这些组件提供了大量的接口和配置,让开发者选择合适的使用场景。这些组件的设计复杂,使用也较繁琐,新人上手有一定的门槛。W3C也在加紧制定Web Components(即组件)的标准,试图制定一个统一的简单实用的标准化的组件概念。我们看看React是如何设计组件模型的以及其和Web Component的区别。

React框架里面使用了简化的组件模型,但更彻底地使用了组件化的概念。React将整个UI上的每一个功能模块定义成组件,然后将小的组件通过组合或者嵌套的方式构成更大的组件。这种做法已经在instagram网站上普遍实施,大家可以看看instagram的前端源代码。 如下通过一个简单的例子来阐述React中模块化的概念。这个例子来自于React的官方网站教程,是完成一个简单的评论框。这个评论框主要包含两个部分,评论列表和评论表单。显示效果如下:

按照React模块组合的设计,把评论框组件commentBox分为两个子组件模块:commentList和commentForm,代码如下:

<div className="commentBox">
  <h1>Comments</h1>
  <CommentList data={this.state.data} />
  <CommentForm onCommentSubmit={this.handleCommentSubmit} />
</div>

commentList和commentForm组件对应的代码如下:

<div className="commentList">
  {commentNodes}
</div>

<form className="commentForm" onSubmit={this.handleSubmit}>
  <input type="text" placeholder="Your name" ref="author" />
  <input type="text" placeholder="Say something..." ref="text" />
  <input type="submit" value="Post" />
</form>

从代码中可以看到CommentList组件又可以划分为comment组件的列表。comment组件代码如下:

<div className="comment">
  <h2 className="commentAuthor">
    {this.props.author}
  </h2>
  <span dangerouslySetInnerHTML= />
</div>

可以看出,为了完成评论框功能,使用React定义了四个不同的组件:commentBox、commentList、commentForm、comment。commentBox是由commentList和commentForm组合而来,commentList是由comment组合而来。这个例子充分体现了React组件化的理念,每个组件的UI和逻辑都定义到了内部,暴露少量的API和外部交互,组件之间组合形成更复杂的组件。总结一下,React的组件具有如下的特性:

  • 可组合:简单组件可以组合为复杂的组件
  • 可重用:每个组件都是独立的,可以被多个组件使用
  • 可维护:和组件相关的逻辑和UI都封装在了组件的内部,方便维护
  • 可测试:因为组件的独立性,测试组件就变得方便很多。

React使用了组件化的设计,所以开发者自然而然和原生的Web Components相提并论,StackExchange上有一篇精彩的讨论,解释了React的组件和原生组件的对比。文章从语言层面、样式的封装、数据绑定、DOM操作方式等这几个方面展开讨论,结论是说两者没有优劣之分,只是编码习惯问题。Web Components规范毕竟还在制定过程中,应该可以从React的组件设计方式上借鉴一些理念。在后续的文章中,会深入探讨React中组件的设计原理及使用。

虚拟DOM

在JavaScript中DOM操作是独立成为一个分支的。各浏览器在实现DOM操作库也是大同小异,都是在单独的模块中实现了DOM操作,由于各种技术上的原因,DOM操作的性能损耗相对于其他操作是很大的。在前端开发中都是需要特别尽量保持较小的DOM操作次数来提高性能。

React作为一个UI框架,不可避免要有界面上元素的交互。为了提高性能,React在操作页面交互时引入了虚拟DOM的概念。虚拟DOM是在React中用JavaScript重新实现的一个DOM模型,和原生的DOM并没有多少关系,只是借鉴了原生DOM的一些概念。虚拟DOM并没有完全实现DOM,只是保留了元素直接的层级关系和少量必要的属性。因为减少了不必要的复杂性,实践校验的结果是虚拟DOM的性能比原生DOM高很多。来看看普通DOM和虚拟DOM在代码上的差别。

如下是使用原生DOM生成的元素:

var a = document.createElement(‘a‘)
a.setAttribute(‘class‘, ‘link‘)
a.setAttribute(‘href‘, ‘https://github.com/facebook/react‘)
a.appendChild(document.createTextNode(‘React‘))

那么使用虚拟DOM则代码为如下:

var a = React.createElement(‘a‘, {
    className: ‘link‘,
    href: ‘https://github.com/facebook/react‘
}, ‘React‘)

可以看到React中使用了自己实现的createElement方法来生成元素DOM结构。

基于React开发中构建的DOM都是通过虚拟DOM进行的。在React的实际的使用中,需要根据不同的数据展现不同的UI,当数据变化时,React会重新构建整个DOM树,然后将当前的DOM树和之前的比较,得到DOM树的区别,然后仅仅把变化的部分反映到实际的浏览器UI更新上。React会在同一个事件循环内合并DOM的变化,只是会对比开始和结束的DOM变化,忽略中间过程的DOM变化。尽管每次数据变化都是重新构建DOM树,但虚拟DOM的操作性能极高。这样使用React时,开发者不在需要关心数据变化时页面上DOM元素的更新,而只是关心各个数据状态下页面实际展现的效果。此外,因为React使用了由JavaScript实现的虚拟DOM,意味着可以在服务器端完成HTML结构的构建。

JSX

JSX是React的重要组成部分,他使用类似XML标记的方式来声明界面及关系,所以他只是一个文档规范。如下是一个在React里面使用JSX的例子:

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

React.render(<HelloMessage name="John" />, mountNode);

可以看到如上使用了JSX的代码,像是HTML和JavaScript代码的混合体。很多人很不习惯这样的编码方式,认为这和我们一直倡导的表现和逻辑分离的思想相违背,是一种倒退。那么React这样的设计用意是啥呢?

React一个主要的设计理念是编写简单容易理解的代码。HTML模板的作用是让表现和逻辑分离,但是很多情况下模板还是严重依赖于业务逻辑,两者没有办法做到完全的松耦合。稍微复杂一点的例子,比如AngularJS使用了一套独特的机制来让UI和逻辑交互,示例代码如下。

<ul class="unstyled">
  <li ng-repeat="todo in todoList.todos">
    <input type="checkbox" ng-model="todo.done">
    <span class="done-"></span>
  </li>
</ul>

使用AngularJS的确从代码角度做到表现和逻辑分离,但是在HTML里面混入了大量的属性标记,这些标记但从语义上很难理解,新手比如要整个熟悉Angular中每个类似ng-*对应的用法及意义才能理解整个逻辑,所以有一定的入门门槛。如上例子使用JSX方式编写如下:

render: function () {
  var lis = this.todoList.todos.map(function (todo) {
    return  (
      <li>
        <input type="checkbox" checked={todo.done}>
        <span className="done-{todo.done}">{todo.text}</span>
      </li>);
  });
  return (
    <ul class="unstyled">
      {lis}
    </ul>
  );
}

可以看到,JSX中除了使用HTML标记之外,并没有复杂的标记。这种自然而直观的方式直接降低了React的学习门槛并且让代码更容易理解。

JSX只是简化了React的使用难度,但并不是必须的。在React中也可以不使用JSX,而是使用原生JavaScript的方式编写代码。在实际使用过程中也是把JSX转换成了JavaScript代码来运行的。React官方网站上提供了一个在线转换JSX到原生JavaScript代码的工具,通过这个工具也可以体会JSX使用上的优势及其内在原理。

Flux

Flux是另外一个独立于React的架构。之所以说Flux是一个架构而不是框架或者类库,是因为Flux仅仅用于配合React框架来处理组件和数据之间的交互。简单来说Flux就是用于管理数据流。和其他MVC框架倡导的双向数据绑定不同,Flux使用了单向数据绑定的机制,即数据模型到视图的流动。如下两个图展示MVC和Flux之间的差异:

Flux中主要使用了三个概念:Dispatcher、Action和Store。这三个概念区别于MVC的model、view和controller概念,因为MVC中更多的是数据双向绑定。

Actions是用于传递数据给Dispatcher的操作集合。Action可能来自于用户界面的操作,也可能是服务器端的数据更新。

Dispatcher是一个全局的分发器,接受Action,并传递给注册的回调函数。

Stores包含了应用的状态及注册到Dispatcher的回调函数,这些函数用于处理业务逻辑。

和React Views最密切的是Store,React view从Store取得state和其他数据,并更新界面。

总结

从以上的React相关设计可以看出,React是以降低前端开发的复杂度为原则的。使用React编写的代码也易于理解,所以适合大规模多人开发,能提高项目的开发效率和质量。

参考链接

时间: 2024-10-05 04:45:04

React框架为什么这么火:React的设计思想的相关文章

React的设计思想——理解JSX和Component

基于HTML的前端界面开发正变得越来越复杂,其本质问题基本都可以归结于如何将来自于服务器端或者用户输入的动态数据高效的反映到复杂的用户界面上.而来自Facebook的React框架正是完全面向此问题的一个解决方案.React带来了很多开创性的思路来构建前端界面,虽然选择React的最重要原因之一是性能,但是相关技术背后的设计思想更值得我们去思考. React项目经理Tom Occhino曾经阐述React诞生的初衷,他提到React最大的价值究竟是什么?是高性能虚拟DOM.服务器端Render.

React 框架和Webpack

基于HTML的前端界面开发正变得越来越复杂,其本质问题基本都可以归结于如何将来自于服务器端或者用户输入的动态数据高效的反映到复杂的用户界面上.而来自Facebook的React框架正是完全面向此问题的一个解决方案,按官网描述,其出发点为:用于开发数据不断变化的大型应用程序(Building large applications with data that changes over time).相比传统型的前端开发,React开辟了一个相当另类的途径,实现了前端界面的高效率高性能开发. 首先,对

React框架

# React框架 ##梳理笔记: **属性设置`style={{marginLeft:"10px"}}`** **添加自定义属性需要使用 data- 前缀** **在 JSX 中使用 JavaScript 表达式.表达式写在花括号 {} 中** **在 JSX 中不能使用 if else 语句,但可以使用 conditional (三元运算) 表达式来替代** ```js render(){ return( <div> <h1>{i == 1 ? 'True!

深入浅出React(一):React的设计哲学 - 简单之美

编者按:自2013年Facebook发布以来,React吸引了越来越多的开发者,基于它的衍生技术,如React Native.React Canvas等也层出不穷.InfoQ精心策划"深入浅出React"系列文章,为读者剖析React开发的技术细节. React最初来自Facebook内部的广告系统项目,项目实施过程中前端开发遇到了巨大挑战,代码变得越来越臃肿且混乱不堪,难以维护.于是痛定思痛,他们决定抛开很多所谓的"最佳实践",重新思考前端界面的构建方式,于是就有

认识React框架

React框架 在大厂面试的时候被问会不会React框架几乎是必须的,可见React框架在现在前端市场的份额.所以说学习React框架的必要性. react框架起源于Facebook的内部项目,因为对市场上的Javascript Mvc框架都不满意,就决定自己写一套,很牛叉吧!当这个框架出来之后,它的优势就被展示出来,于2013年5月就开源了.之后版本就一直更新,13-17年主要是低版本的(15版),17年9月出的高版本(16版),两个版本间的改动挺大的,后续会介绍改动间的差别.由于 React

从 setState promise 化的探讨 体会 React 团队设计思想

从 setState 那个众所周知的小秘密说起... 在 React 组件中,调用 this.setState() 是最基本的场景.这个方法描述了 state 的变化.触发了组件 re-rendering.但是,也许看似平常的 this.setState() 里面却也许蕴含了很多鲜为人知的设计和讨论. 相信很多开发者已经意识到,setState 方法"或许"是异步的.也许你觉得,看上去更新 state 是如此轻而易举的操作,这并没有什么可异步处理的.但是要意识到,因为 state 的更

当react框架遇上百度地图

百度地图官方文档的使用指导是这样说的:在页面中引入<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=你获取的秘钥"></script>,然后就可以使用脚本中引入的BMap对象去调用各种API了 我遇到的问题: 我在入口文件--index.html引入上面那段脚本后,而在另外一个JS文件里访问BMap时候报错了,提示BMap is not

谈谈出入React框架踩过的坑

1 在JSX的元素中写入内联样式,例如<div style={"color:blue"}></div> 报错:warning:Style prop value must be an object  react/style-prop-object 原因:在React框架的JSX编码格式要求,style必须是一个对象 解决方法:除了外部那个表示Javascript语句的花括号外,里面必须再写一个花括号{}包含的对象,例如<div style={ {  colo

学习React前端框架,报错 &#39;React&#39; must be in scope when using JSX react/react-in-jsx-scope

问题 import react from 'react'  改成  import React from 'react'   小写 react  改成 React 学习React前端框架,报错 'React' must be in scope when using JSX react/react-in-jsx-scope 原文地址:https://www.cnblogs.com/BensonHai/p/9952156.html