我是怎么从顾虑到热爱ReactJS的(与AngularJS经典MVC数据绑定的对比)


发布者 ourjs  发布时间 1432862790604
关键字 JS学习  JavaScript 
如果你问我两个月前怎么看 React,我可能会说:

我的模板在哪?在我的JavaScript里写这么多HTML干什么?JSX看起来很怪!赶快把它从我的项目里面去掉!
这是因为我还不了解它。现在我保证,React决定是正常的路径,请听我尾尾道来。


经典的MVC


在一个交互式应用程序中状态的管理是一切罪恶的根源。“传统”的方式是采用MVC架构,或者是一些变种。

MVC提出你的模型(Model)是检验真理的唯一来源 - 所有的状态都在那里。视图(View)源自模型,并且必须跟模型保持同步。当模型转变时,视图也要同步改变

最后,用户通过控制器(Controller)控制交互,由它更新模型。到目前为止,这工作地很好。





当Model改变时重绘View


这看起来很简单。首先,我们需要来详细我们的View - 它是一个对DOM的映射。然后,每当用户更新模型时重绘整个DOM,对吧?不幸的是,事情不是这么简单,原因有二:

1. DOM 实现上是有状态的, 像input文本的内容。如果你重绘整个DOM, 这部分内容就会丢失。
2. DOM 操作 (像移除插入的结点) 真的非常慢. 持续不断地重绘会导致严重的性能问题。


所以,我们怎样同步Model和View来避免上面的问题?


数据绑定 Data binding


在过去3年,框架级别的通用解决方案是采用数据绑定。

数据绑定是让你的模型和视图,拥有自动同步的能力。通常情况下,是将JavaScript对象和DOM进行同步。

它通过你的数据声明的组件之间的依赖关系来实现。状态的变化会在整个应用程序中传播并通知所有依赖的对象,然后自动更新。

让我们来看看它是如何工作的,还有一些著名的框架。

Knockout


Knockout主张MVVM模式,并帮助您实现“View”部分:


// View (a template) <p>First name: <input data-bind="value: firstName" /></p> <p>Last name: <input data-bind="value: lastName" /></p> <h2>Hello, <span data-bind="text: fullName"> </span>!</h2> // ViewModel (diplay data... and logic?) var ViewModel = function(first, last) { this.firstName = ko.observable(first); this.lastName = ko.observable(last); this.fullName = ko.pureComputed(function() { // Knockout tracks dependencies automatically. It knows that fullName depends on firstName and lastName, because these get called when evaluating fullName. return this.firstName() + " " + this.lastName(); }, this); };

然后,万事大吉了。改变任一输入的值将触发DOM的变化。你不用写数据与视图关连的逻辑代码。效果不错,是吧?

为什么模型是真理的唯一来源?这个ViewModel应该从哪里获取状态?它是如何知道Model的变化的?这是很有趣的问题。


Angular


Angular介绍了如果在Model和View之间同步数据。下图来自其文档:





但是......View应该与Model直接通信吗?难道他们是紧耦合的?

无论如何,让我们来看看Hello World示例:

// View (a template) 
<div ng-controller="HelloController as hello">  
  <label>Name:</label>
  <input type="text" ng-model="hello.firstName">
  <input type="text" ng-model="hello.lastName">
  <h1>Hello {{hello.fullName()}}!</h1>
</div>

// Controller 
angular.module('helloApp', [])  
.controller('HelloController', function() {
  var hello = this;
  hello.fullName = function() {
    return hello.firstName + hello.lastName;
  };
});

通过这个例子,Controller看起来像是拥有自己的状态,而且表现的像个Model或者一个ViewModel?假设Model是由其它东西实现的,那它是如何跟Controller保持同步的呢?

data binding的问题


数据绑定在小的例子里工作地很好。然而,当你的app不断地迭代时。你可能会碰到下面的问题。

声明依赖会快速地引入循环

最常见的问题是在应对状态变化时所产生的副作用。从Flux的这篇报道可以很清楚地了解依赖地狱的蠕变:





在这种情况下,你能预测一个Model发生变化时会发生什么吗?推理是非常非常困难的,因为它的执行次序可能是非常随意的。

模板和显示逻辑被人为地割裂

视图的作用是什么?呈现的数据显示给用户。ViewModel是干什么的?呈现的数据显示给用户。有什么区别?没有!


模板分离技术,我不关注〜 皮特·亨特

最后,一​​个视图组件应该能够操纵它的数据,并能以所希望的格式呈现它。但是,所有的模板语言本质上是残缺的:他们永远不能达到同样的表现力和效能的代码。


非常简单,{{# each}}, ng-repeat 和 databind="foreach" 都仅能替代天然的和琐碎JavaScript中的一个for循环。不能再进一步。因为,这里没有filter或map给你用。


Data binding 是围绕重新渲染的Hack手法


当状态变化时,人们都希望重新渲染整个应用。通过这种方式,我们可以阻止一个万恶的问题:状态是随时间变化的。


了解Facebook的React框架



事实证明,他们做到了。React使用一个虚拟DOM(virtual DOM)来解决上面的问题。

virtual DOM到底是什么?

我们来看一看React的例子


var Hello = React.createClass({  
    render: function() {
        return
Hello {this.props.name}
;
    }
});

React.render(, document.getElementById('container')); 


这就是一个React组件的所有代码。你只需要有一个渲染方法。复杂吗?

OK,
是什么?这不是JavaScript的写法!确实JS里肯定没有这个东西。


你的新朋友: JSX


这个码被实际是用JSX写的,一个Javascript的超集,其使用括号语法定义组件。上面的代码,当编译成JavaScript时,将变成:


var Hello = React.createClass({displayName: "Hello",  
    render: function() {
        return React.createElement("div", null, "Hello ", this.props.name);
    }
});

React.render(React.createElement(Hello, {name: "World"}), document.getElementById('container'));  

你有没有注意到调用的createElement?这些对象组件的Virtual DOM实现。

很简单:首先React在内存中组装整个应用程序的结构,使用这些对象。然后,它把这个结构转化为实际的DOM节点,将它们插入您浏览器的DOM中。

OK,但是为什么我们的HTML要变成那些奇怪的createElement函数呢?


Virtual DOM 非常快


正如我们已经讨论的,操作DOM贵的离谱,所以这个操作做得越少越好。

React的Virtual DOM,使得这个操作变得很快。通过这种方式,React能够比较两种DOM树的差异,然后计算出能使DOM新化所需的最小变化。这意味着两件事情:

如果输入文本重新渲染,React不会触及输入。没有更多的状态变化!

如果React重新渲染Text的内容。它不会动input。不会有状态丢失。

比较的Virtual DOM的性能还可以,当它会在准备改变DOM前进行充分的比较,它只会执行尽可能少的操作。因此渲染是很快的!


React印射状态到DOM中


Virtual DOM在渲染进行进行比较的是React魔法的一部分。并且它能从根本上使我们能够有一个更简单的框架。多么简单?


这是一个React组件应该有的功能,它能将应用程序的状态映射到DOM中。你能发挥JavaScript的全部能力来描述你的UI - 循环,函数,Scope,组件,模块 - 它不是一个残缺的模板语言。


var CommentList = React.createClass({  
  render: function() {
    var commentNodes = this.props.data.map(function (comment) {
      return (
        <Comment author={comment.author}>
          {comment.text}
        </Comment>
      );
    });
    return (
      <div className="commentList">
        {commentNodes}
      </div>
    );
  }
});

var CommentBox = React.createClass({  
  render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
        <CommentList data={this.props.data} />
      </div>
    );
  }
});

React.render(  
  <CommentBox data={data} />,
  document.getElementById('content')
);


开始用React


第一次用React可能有点另人生畏。它提出了一个非常大的风格转变,这其实不是很舒服。然而,当你开始用时,你会发现优势明显。

快乐编码!






回复 (18)
  • #
  • #1 吴伏问 1432870858347

    带有强烈的主观意见啊

  • #2 蔡议劣 1432896490289

    机器翻译

  • #3 open-node 1433123869298

    确实解决了ng的很多问题。

  • #4 危方决 1433296183267

    以我的Backbone.js背景看起来,React值得拥有。

  • #5 c4605 1433302692490

    我最近也用了一段时间的 reactjs ,所以我想有还是稍微有点资格来谈论 angularjs 和 reactjs 的

    文中提到了 angularjs 的两个很重要的问题:controller 拥有了自己的状态,和声明依赖比较容易出现循环依赖(而且这和 data-binding 毫无关系)

    我同意 facebook 确实提出了一个非常不错的解决方案,但这方案与 virtual dom 没有直接的关系(所以你说这东西解决了上面的问题我认为是不合适的),这个方案是 Flux ,通过发布事件的方式来提醒模型更新状态,进而更新所有相关 DOM ,这才是解决之道。而 virtual dom 只是这个解决方案里保证性能的一环而已。

    而 data-binding ,实话说看到一些 reactjs 的趸拥一天到晚扯说 data-binding 是邪恶的让我觉得很莫名其妙。data-binding 只是一种模式而已,reactjs 内置了数据的单向绑定难道这就不是 data-binding ?而且 reactjs 还带了一个扩展用来实现数据的双向绑定按你们来说又是什么意思?难道在 vitrual dom 的 onChange 属性里传一个回调函数然后更新 state 或者发出事件更新模型就不是数据绑定了?那么其他框架实现双向绑定的方法“监听 DOM 事件,更新 viewmodel”也不能算是双向绑定咯?因为这其实和在 reactjs 里做的没有任何区别

    我的观点就是,reactjs 是一个不错的东西,flux 解决了不少其他 MVVM 框架的问题,data-binding 绝对是一种进步

  • #6 廉也办 1433732667502

    这个翻译.... 确定不是机器翻的?

  • #7 王十比 1434268141672

    什么翻译,还有你确定作者真的了解过ng?或者说mvc/mvvm,所谓的virtual dom其实就是另一种presentation model,没本质区别。

    写的示例代码让我觉得你肯定没用过ng,ng最关键的scope都没出现,谁和你说controller是有状态的,是你的错误理解,错误代码吧。

    ng是入门容易精通难,写出高性能需要一定水平,适合全栈工程师。其强大功能非常强大,特别适合数据驱动UI的程序。 要纯考虑性能,jquery绝对ok。

    没用过reactjs,不好发表太多。但是看楼主代码,只想说,项目大了,维护成本更高。这一点深刻在jquery中体会过。 所谓的virtual dom,就是与UI的耦合,使用ng,我完全可以把一个controller直接用到windows 10上,只要简单修改view的代码而保持业务代码完全不变。

  • #8 倪切轨 1434815807512

    @c4605 #4


    对滴.. react 有了 flux 才与 ng 等框架比肩的实力

  • #9 张冬自 1436753599595























    1. 列表

    --

    ##

    ##

    ==

  • #10 张冬自 1436753871334

    介绍react的时候,没必要拉上angularjs提升自身价值。 两个不是一个重量级的东西。 干的事情也不完全相同。 没有完全了解两者的使用场景总喜欢拉低对手其实并没有什么乱用。

  • #11 章个丹 1438743076080

    目前,如果项目中使用了很多的依赖DOM操作特效的插件,例如 jQuery.XXXX ,那最好不要使用 React。

    我觉得React目前最适合页面不是很复杂的移动端Web界面,而且浏览器内存也消耗少。

  • #12 document.body.innerHTML = '' 1448961938000

    目前,如果项目中使用了很多的依赖DOM操作特效的插件,例如 jQuery.XXXX ,那最好不要使用 React。

    我觉得React目前最适合页面不是很复杂的移动端Web界面,而且浏览器内存也消耗少。

  • #13 母仆闭 1449192583659

    @王十比 #6 ng最关键的scope都没出现?哥们,你知道controllerAs吗

  • #14 邬刃吉 1456333005057

    什么烂翻译。。。。。

  • #15 邹过头 1459993979265

    @章个丹 #10

    为啥

  • #16 魔法师 1480247028651

    @邹过头 #14 他说反了,简单的页面web页面最好不要用react,因为react的每一个组件都是独立的,正因为独立所以编写起来要比正常的麻烦许多,但是随着项目的进行,项目变得越来越复杂,这个时候react的优势就体现出来了

  • #17 邱玉叹 1522208833113


    标题

    ##

  • #18 邱玉叹vuyvgjvjgvjhjvhvjh 1522208863449












    ----------xia ji ba che dan

    ##

微信扫码 立即评论




 热门文章 - 分享最多
  1. NativeScript的竞争者React Native:又一个用JavaScript写原生iOS应用的项目
  2. 2015年度开发者调查:JS最流行;ObjC工资最高;最想学Android
  3. 基于JavaScript的DDoS首次通过安全的浏览器发动攻击(百度被劫持攻击Github的原理和过程)
  4. 编写高性能HTML网页应用
  5. WordPress 4.3核心功能将放弃PHP并使用Node.JS重写[4.1]
  6. 几款开源的图形化Redis客户端管理软件
  7. JavaScript变量作用域(Variable Scope)和闭包(closure)的基础知识
  8. Image Lazy Load:那些延时加载图片的开源插件(jQuery)
  9. 创建自定义的jQuery补间动画运动函数及其实现的数学原理
  10. Mozilla Firefox将停止支持不安全的HTTPS

 相关阅读
  1. 我是怎么从顾虑到热爱ReactJS的(与AngularJS经典MVC数据绑定的对比)
  2. JSON序列化(stringify)对象时排除某些属性的两种方法
  3. JavaScript变量作用域(Variable Scope)和闭包(closure)的基础知识
  4. 用jQuery为跳转链接锚点添加平滑滚动动画效果(如回到顶部按钮)
  5. 用纯css改变下拉列表select框的默认样式
  6. Atom编辑器嵌入Node.JS引擎实践
  7. AngularJS和$scope.$apply()用法的最佳实践
  8. 微软,IBM,ARM等大公司先后加入对Node.js/io.js的支持
  9. 用原生HTML5控件实现输入框自动提示(下拉列表补全)功能
  10. 让我们写快速的JavaScript,JS性能优化小窍门

  开源的 OurJS
OurJS开源博客已经迁移到 OnceOA 平台。

  关注我们
扫一扫即可关注我们:
OnceJS

OnceOA