欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入理解JavaScript的React框架的原理

 更新時間:2015年07月02日 11:28:29   投稿:goldensun  
這篇文章主要介紹了JavaScript的React框架的原理,包括其與AngularJS的比較,需要的朋友可以參考下

如果你在兩個月前問我對React的看法,我很可能這樣說:

  •     我的模板在哪里?javascript中的HTML在做些什么瘋狂的事情?JSX開起來非常奇怪!快向它開火,消滅它吧!

 那是因為我沒有理解它.

我發(fā)誓,React 無疑是在正確的軌道上, 請聽我道來.

Good old MVC

在一個交互式應(yīng)用程序一切罪惡的根源是管理狀態(tài)。
“傳統(tǒng)”的方式是MVC架構(gòu),或者一些變體。

MVC提出你的模型是檢驗真理的唯一來源 - 所有的狀態(tài)住在那里。
視圖是源自模型,并且必須保持同步。
當(dāng)模式的轉(zhuǎn)變,所以沒有查看。

最后,用戶交互是由控制器,它更新模型抓獲。
到目前為止,一切都很好。

201572112250707.png (500×550)

模型發(fā)生變化時就要對視圖進(jìn)行渲染

這看起來相當(dāng)簡單。首先,我們需要描述視圖——它是如何將模型狀態(tài)轉(zhuǎn)換到DOM上去的。然后,用戶一發(fā)生了什么操作我們就要對模型進(jìn)行更新,并且要對整個頁面進(jìn)行重新渲染... 對不? 沒這么快哦. 不幸的事,這其實并沒有這么直接,因為如下兩個原因:

  •     DOM實際上有某種狀態(tài),就比如一個文本輸入框中的內(nèi)容. 如果你完全作廢你的DOM來進(jìn)行重新渲染,這樣的內(nèi)容會丟失掉.
  •     DOM 操作 (像刪除和插入節(jié)點) 真的慢. 頻繁的渲染會導(dǎo)致嚴(yán)重的性能問題.

那么我們?nèi)绻诒苊膺@些問題的前提下保持模型和視圖同步呢?
數(shù)據(jù)綁定

過去三年,被引進(jìn)用來解決這個問題最常用多框架功能就是數(shù)據(jù)綁定.

數(shù)據(jù)綁定能自動地保持模型和視圖的同步. 通常在JavaScript中就代表了對象和DOM.

它會通過讓你聲明應(yīng)用中各個塊之間的依賴來對這一同步進(jìn)行打包。狀態(tài)的變化會在整個應(yīng)用程序中蔓延,然后所有的依賴塊都會被自動更新.

讓我們來看看一些有名的框架中它實際是如何運(yùn)作的吧.

Knockout

Knockout 主張使用的是 MVVM (模型-視圖-視圖模型) 方法,并且?guī)湍銓崿F(xiàn)了“視圖”的部分:
 

// 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);
};

而這就是了. 不管改變那邊的輸入值都在讓span中發(fā)生變化。你從來都不需要寫代碼將其進(jìn)行綁定。這多酷啊,呵?

但是等等,模型不是真相的來源么? 這里的視圖模型從來獲得它的狀態(tài)呢? 它是怎么知道模型發(fā)生了變化的呢? 有趣的問題啊.

Angular

Angular 采用保持模型和視圖同步的方式描述了數(shù)據(jù)綁定. 文檔時這么描述的:

201572112357063.png (400×290)

但是... 視圖應(yīng)該直接通模型打交道么? 這樣它們不久緊緊的耦合起來了么?

不管怎么樣,我們還是來義務(wù)地看看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;
 };
});

從這個示例中,看起來像是控制器有了狀態(tài),并且有類似模型的行為 - 或者也許是一個視圖模型? 假設(shè)模型在其它的地方, 那它是如何保持與控制器的同步的呢?

我的頭開始有點兒疼了.
數(shù)據(jù)綁定的問題

數(shù)據(jù)綁定在小的例子中運(yùn)行起來很不錯。不過,隨著你的應(yīng)用規(guī)模變大,你可能會遇到下面這些問題.

聲明的依賴會很快引入循環(huán)

最經(jīng)常要處理的問題就是對付狀態(tài)中變化的副作用。這張圖來自 Flux 介紹,它解釋了依賴是如何開始挖坑的:

201572112422504.png (1587×900)

你能預(yù)計到當(dāng)一個模型發(fā)生變化時跟著會發(fā)生什么改變么? 當(dāng)依賴發(fā)生變化時,對于可以任意次序執(zhí)行的代碼你很難推理出問題的起因。
模板和展示邏輯被人為的分離

視圖扮演了什么角色呢? 它扮演的就是向用戶展示數(shù)據(jù)的角色。視圖模型扮演的角色又是什么呢? 它扮演的也是向用戶展示數(shù)據(jù)的角色?有啥不同?完全沒有!

  •     毫無疑問,模板割裂了計數(shù)  ~ Pete Hunt

最后,視圖組件應(yīng)該能操作其數(shù)據(jù)并以需要的格式對數(shù)據(jù)進(jìn)行展示。然后,所有的模板語言本質(zhì)上都是有缺陷的:它們從來都不能達(dá)到跟代碼一樣的表現(xiàn)力和功能。

很簡單, {{# each}}, ng-repeat 和 databind="foreach" 這些都是針對 JavaScript 中某些原生和瑣碎事務(wù)的拙劣替代物。而它們不會更進(jìn)一步走得更遠(yuǎn)。因此它們不會為你提供過濾器或者映射。

數(shù)據(jù)綁定是應(yīng)重新渲染而生的小技巧

什么是圣杯不再我們的討論之列。每個人總是想要得到的是,當(dāng)狀態(tài)發(fā)生變化時能重新對整個應(yīng)用進(jìn)行渲染。這樣,我們就不用去處理所有麻煩問題的根源了:狀態(tài)總是會隨著時間發(fā)生變化——給定任何特定的狀態(tài),我們就可以簡單的描述出應(yīng)用回是什么樣子的。

好了,問題清楚了。哥們,我希望某些大公司能組個超能天才開發(fā)者團(tuán)來真正解決這個問題...
擁抱Facebook的React

事實證明他們做到了。React實現(xiàn)了一個虛擬的DOM,一種給我們帶來的圣杯的利器.
虛擬的DOM是啥東西呢?

很高興你能這么問?讓我們來看看一個簡單React示例.
 

var Hello = React.createClass({ 
  render: function() {
    return <div>Hello {this.props.name}</div>;
  }
});
React.render(<Hello name="World" />, document.getElementById('container'));

這就是一個React組件的所有API。你必須要有一個渲染方法。復(fù)雜吧,呵呵?

OK, 但是 <div> 是什么意思? 那不是 JavaScript 啊! 對了,它就不是.

你的新伙伴,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 調(diào)用的代碼么? 這些對象組成了虛擬 DOM 的實現(xiàn)。

很簡單 : React 首先在內(nèi)存中對應(yīng)用的整個結(jié)構(gòu)進(jìn)行了組裝。然后它會把這個結(jié)構(gòu)裝換成實際的 DOM 節(jié)點并將其插入瀏覽器的 DOM 中。

OK,但是用這些奇怪的 createElement 函數(shù)編寫 HTML 的目的是什么呢?
 
虛擬的DOM就是快

我們已經(jīng)討論過, 操作 DOM 消耗大得離譜,因此它必須以盡可能少的時間完成。

React 的虛擬 DOM 使得兩棵 DOM 結(jié)構(gòu)的比對真正快起來,并且能確切的找到它們之間有什么變化. 如此,React 就能計算出更新 DOM 所需要做出的最小變更。

實話說,React 能比對兩棵 DOM 樹,找出它所要執(zhí)行的最小操作集。這有兩個意義:

  1.     如果一個帶有文本的輸入框被重新渲染,React 會知道它有的內(nèi)容, 它不會碰那個碰那個輸入框。不會有狀態(tài)發(fā)生丟失的!
  2.     比對虛擬 DOM 開銷一點也不昂貴,因此我們想怎么比對都可以。當(dāng)其準(zhǔn)備好要對 DOM 進(jìn)行實際的修改時,它只會進(jìn)行最少量的操作。沒有額外的拖慢布局之虞!

那我們還要在狀態(tài)發(fā)生變化時記住這兩個對整個 app 進(jìn)行重新渲染的問題么?

這都是過去式了。

React 將狀態(tài)映射到 DOM

React 中只有虛擬 DOM 的渲染和比對是神奇的部分。其優(yōu)秀性能是使得我們擁有簡化了許多的整理架構(gòu)的基礎(chǔ)。有多簡單呢?

     React 組件都是冪等(一個冪等操作的特點是其任意多次執(zhí)行所產(chǎn)生的影響均與一次執(zhí)行的影響相同)的函數(shù)。它們能在任意一個實時的點來描述你的UI。~ Pete Hunt, React: 對最佳實踐的重新思考

簡單的冪等函數(shù)。

React 組件整個就是這么一個東西,真的。它將當(dāng)前的應(yīng)用狀態(tài)映射到了 DOM。并且你也擁有JavaScript的全部能力去描述你的 UI——循環(huán),函數(shù),作用域,組合,模塊 - 不是一個蹩腳的模板語言哦.
 

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 一開始會有點令人生畏。它提出了一個實在是太大了點的模式轉(zhuǎn)變,這總有點令人不舒服。不過,當(dāng)你開始使用它時其優(yōu)勢會變得清楚起來。

React 文檔很優(yōu)秀. 你應(yīng)該照著教程對其進(jìn)行一下嘗試。我確信如果你給它一個機(jī)會,你肯定會愛上她。

編碼快樂!

相關(guān)文章

  • JavaScript內(nèi)核之基本概念

    JavaScript內(nèi)核之基本概念

    本文將聚焦于JavaScript中的基本概念,這些概念與傳統(tǒng)語言有比較大的不同,因此單獨列出一章來做專門描述,理解本章的概念對書中后續(xù)章節(jié)的概念,代碼的行為等會有很大的幫助,讀者不妨花比較大的時間在本章,即使你對JavaScript已經(jīng)比較熟悉,也建議通讀本文
    2011-10-10
  • 深入分析Javascript事件代理

    深入分析Javascript事件代理

    JavaScript事件是所有網(wǎng)頁互動性的根基。在傳統(tǒng)的事件處理中,事件處理器將有可能導(dǎo)致內(nèi)存泄露或者是性能下降,JavaScript事件代理則是一種簡單的技巧,通過它你可以把事件處理器添加到一個父級元素上,這樣就避免了把事件處理器添加到多個子級元素上。
    2016-01-01
  • javascript 基礎(chǔ)篇4 window對象,DOM

    javascript 基礎(chǔ)篇4 window對象,DOM

    window這個對象我們之前也稍微接觸過了,其實就是對窗體進(jìn)行操作,利用這個對象我們可以實現(xiàn)很多的操作,比如窗口移動啊,設(shè)置窗口大小啊等等
    2012-03-03
  • js學(xué)習(xí)筆記之事件處理模型

    js學(xué)習(xí)筆記之事件處理模型

    本篇文章主要介紹了js學(xué)習(xí)筆記之事件處理模型,對初學(xué)這具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2016-10-10
  • 深入解讀JavaScript中的Iterator和for-of循環(huán)

    深入解讀JavaScript中的Iterator和for-of循環(huán)

    這篇文章主要介紹了JavaScript中的Iterator和for-of循環(huán),是JS入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-07-07
  • jquery和javascript的區(qū)別(常用方法比較)

    jquery和javascript的區(qū)別(常用方法比較)

    jquery 就對javascript的一個擴(kuò)展,封裝,就是讓javascript更好用,更簡單,為了說明區(qū)別,下面與大家分享下JavaScript 與JQuery 常用方法比較
    2013-07-07
  • 5個最頂級jQuery圖表類庫插件【jquery插件庫】

    5個最頂級jQuery圖表類庫插件【jquery插件庫】

    這篇文章主要介紹了5個最頂級jQuery圖表類庫插件【jquery插件庫】,需要的朋友可以參考下
    2016-05-05
  • javascript中有趣的反柯里化深入分析

    javascript中有趣的反柯里化深入分析

    國內(nèi)對前端的研究在某些方面也不遜色于國外,反科里化的話題來自javascript之父Brendan Eich去年的一段twitter,需要深入理解的朋友可以參考本文
    2012-12-12
  • js寶典學(xué)習(xí)筆記(上)

    js寶典學(xué)習(xí)筆記(上)

    js寶典學(xué)習(xí)筆記(上)...
    2007-01-01
  • Javascript中的數(shù)據(jù)類型之旅

    Javascript中的數(shù)據(jù)類型之旅

    JavaScript 是一種弱類型或者說動態(tài)語言。這意味著你不用提前聲明變量的類型,在程序運(yùn)行過程中,類型會被自動確定。這也意味著你可以使用同一個變量保存不同類型的數(shù)據(jù)。
    2015-10-10

最新評論