日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
在Ember中處理異步

許多 Ember 的概念,比如綁定和計(jì)算屬性,其設(shè)計(jì)是為了完成異步行為的處理。

按需求定制制作可以根據(jù)自己的需求進(jìn)行定制,成都做網(wǎng)站、網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè)構(gòu)思過(guò)程中功能建設(shè)理應(yīng)排到主要部位公司成都做網(wǎng)站、網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè)的運(yùn)用實(shí)際效果公司網(wǎng)站制作網(wǎng)站建立與制做的實(shí)際意義

沒(méi)有 Ember 的情況

我們首先來(lái)看一看用 jQuery 或基于事件的 MVC 框架如何管理異步行為。

讓我們使用一個(gè) web 應(yīng)用中最常見(jiàn)的異步行為——發(fā)起一個(gè) Ajax 請(qǐng)求——來(lái)作為例子。 瀏覽器發(fā)起 Ajax 請(qǐng)求的 API 提供了一個(gè)異步的 API。jQuery 包裝器也可以實(shí)現(xiàn):

 
 
 
  1. jQuery.getJSON('/posts/1', function(post) { 
  2.   $("#post").html("

    " + post.title + "

    " + 
  3.     "
    " + post.body + "
    "); 
  4. }); 

在純 jQuery 應(yīng)用中,你會(huì)用這個(gè)回調(diào)來(lái)隨意進(jìn)行要更改到 DOM 的更改。

當(dāng)使用一個(gè)基于事件的 MVC 框架,會(huì)把邏輯從回調(diào)中拿出而放進(jìn)模型和視圖對(duì)象里。 這改進(jìn)了很多東西,但仍未擺脫顯式處理異步回調(diào)的需求:

 
 
 
  1. Post = Model.extend({ 
  2.   author: function() { 
  3.     return [this.salutation, this.name].join(' ') 
  4.   }, 
  5.   toJSON: function() { 
  6.     var json = Model.prototype.toJSON.call(this); 
  7.     json.author = this.author(); 
  8.     return json; 
  9.   } 
  10. }); 
  11. PostView = View.extend({ 
  12.   init: function(model) { 
  13.     model.bind('change', this.render, this); 
  14.   }, 
  15.   template: _.template("

    <%= title %>

    <%= author %>

    <%= body %>
    "), 
  16.   render: function() { 
  17.     jQuery(this.element).html(this.template(this.model.toJSON()); 
  18.     return this; 
  19.   } 
  20. }); 
  21. var post = Post.create(); 
  22. var postView = PostView.create({ model: post }); 
  23. jQuery('#posts').append(postView.render().el); 
  24. jQuery.getJSON('/posts/1', function(json) { 
  25.   // set all of the JSON properties on the model 
  26.   post.set(json); 
  27. }); 

這個(gè)例子沒(méi)有用任何特殊的 JavaScript 庫(kù),但它的實(shí)現(xiàn)途徑是事件驅(qū)動(dòng)的 MVC 框架 中的典型。它實(shí)現(xiàn)了異步事件的組織,但異步行為仍然在核心程序模型中。

Ember 的方法

總體而言,Ember 的目的是消除顯式形式的異步行為。如我們之后會(huì)見(jiàn)到的,這給予了 Ember 合并多個(gè)具有相同結(jié)果事件的能力。

它也提供了高層抽象,消滅手動(dòng)注冊(cè)/反注冊(cè)事件監(jiān)聽(tīng)器來(lái)執(zhí)行大多數(shù)任務(wù)的需求。

你一般會(huì)為這個(gè)例子使用用 ember-data ,當(dāng)讓我們看看如何用 jQuery 來(lái)為 Ember 中的 Ajax 模型化上面的例子。

 
 
 
  1. App.Post = Ember.Object.extend({ 
  2. }); 
  3. App.PostController = Ember.ObjectController.extend({ 
  4.   author: function() { 
  5.     return [this.get('salutation'), this.get('name')].join(' '); 
  6.   }.property('salutation', 'name') 
  7. }); 
  8. App.PostView = Ember.View.extend({ 
  9.   // the controller is the initial context for the template 
  10.   controller: null, 
  11.   template: Ember.Handlebars.compile("

    {{title}}

    {{author}}

    {{body}}
    ") 
  12. }); 
  13. var post = App.Post.create(); 
  14. var postController = App.PostController.create({ content: post }); 
  15. App.PostView.create({ controller: postController }).appendTo('body'); 
  16. jQuery.getJSON("/posts/1", function(json) { 
  17.   post.setProperties(json); 
  18. }); 

與上面的例子相反,Ember 的實(shí)現(xiàn)方法消滅了當(dāng) post 的屬性變更時(shí)顯式注冊(cè)觀察者 的需求。

{{title}} 、 {{author}} 和 {{body}} 模板元素被限定到 PostController 上的那些元素中。當(dāng) PostController 的內(nèi)容更改,它自動(dòng)傳播那些變更到 DOM。

為 author 使用一個(gè)計(jì)算屬性消滅了在底層屬性變更時(shí)顯式地調(diào)用回調(diào)中計(jì)算的需 求。

除此之外,Ember 的綁定系統(tǒng)自動(dòng)跟蹤從 getJSON 回調(diào)中設(shè)置的 salutation 和 name 到 PostController 中的計(jì)算屬性,并且始終把變化傳播到 DOM 中。

益處

因?yàn)?Ember 經(jīng)常負(fù)責(zé)傳播變更,它可以保證在響應(yīng)每個(gè)用戶事件上一個(gè)變更只傳播一 次。

讓我們?cè)倏匆豢?author 計(jì)算屬性。

 
 
 
  1. App.PostController = Ember.ObjectController.extend({ 
  2.   author: function() { 
  3.     return [this.get('salutation'), this.get('name')].join(' '); 
  4.   }.property('salutation', 'name') 
  5. }); 

因?yàn)槲覀円呀?jīng)指定了它依賴(lài)于 salutation 和 name ,這兩個(gè)依賴(lài)的任何一個(gè)的變 更都會(huì)使屬性無(wú)效,這會(huì)觸發(fā)對(duì) DOM 中 {{author}} 的更新。

想象在響應(yīng)一個(gè)用戶事件時(shí),我要做這些事:

 
 
 
  1. post.set('salutation', "Mrs."); 
  2. post.set('name', "Katz"); 

你會(huì)臆斷這些變更會(huì)導(dǎo)致計(jì)算屬性被無(wú)效兩次,導(dǎo)致更新 DOM 兩次。而事實(shí)上,這在 使用事件驅(qū)動(dòng)的框架上確實(shí)會(huì)發(fā)生。

在 Ember 中,計(jì)算屬性會(huì)只重新計(jì)算一次,并且 DOM 也只會(huì)更新一次。

這是如何實(shí)現(xiàn)的呢?

當(dāng)你對(duì) Ember 中的一個(gè)屬性做出更改,它不會(huì)立即傳播變更。除此之外,它立即無(wú)效 任何有依賴(lài)的屬性,但把實(shí)際的修改放入隊(duì)列來(lái)讓它在之后發(fā)生。

對(duì) salutation 和 name 屬性都修改會(huì)無(wú)效 author 屬性?xún)纱?,但?duì)列會(huì)智能地 合并那些變更。

一旦所有當(dāng)前用戶事件的事件處理器完成,Ember 刷新隊(duì)列,把變更向下傳播。在這種 情況下,這意味著被無(wú)效的 author 屬性會(huì)無(wú)效 DOM 中的 {{author}} ,這會(huì)讓 單次請(qǐng)求只重新計(jì)算信息并更新自己一次。

這個(gè)機(jī)制是 Ember 的根基。 在 Ember 中,應(yīng)該總是假定一個(gè)你所做變更的副作 用會(huì)在之后發(fā)生。通過(guò)做這個(gè)假設(shè),你允許 Ember 來(lái)合并單次調(diào)用中相同的副作用。

總而言之,事件驅(qū)動(dòng)系統(tǒng)的目標(biāo)是從監(jiān)聽(tīng)器產(chǎn)生的負(fù)效用中解耦數(shù)據(jù)操作,所以你不應(yīng) 該假定同步的副作用,即使在一個(gè)更關(guān)注事件的系統(tǒng)中。事實(shí)上,在 Ember 中副作用 不會(huì)立刻傳播,消除了欺騙并偶然地把應(yīng)該分開(kāi)的代碼耦合在一起的誘因。

副作用回調(diào)

既然你不能依賴(lài)同步的副作用,你會(huì)好奇如何確保特定的行為在恰好的時(shí)間發(fā)生。

例如,想象你有一個(gè)包含一個(gè)按鈕的視圖,并且你想用 jQuery UI 來(lái)樣式化這個(gè)按 鈕。因?yàn)橐晥D的 append 方法,如同 Ember 中的其它東西,推遲了它的副作用,怎 樣在正確的時(shí)間執(zhí)行 jQuery UI 代碼?

答案是生命周期回調(diào)。

 
 
 
  1. App.Button = Ember.View.extend({ 
  2.   tagName: 'button', 
  3.   template: Ember.Handlebars.compile("{{view.title}}"), 
  4.   didInsertElement: function() { 
  5.     this.$().button(); 
  6.   } 
  7. }); 
  8. var button = App.Button.create({ 
  9.   title: "Hi jQuery UI!" 
  10. }).appendTo('#something'); 

這種情況下,一旦按鈕真正出現(xiàn)在 DOM 中,Ember 會(huì)觸發(fā) didInsertElement 回 調(diào),然后你可以做任何你想要做的工作。

生命周期回調(diào)方法有很多好處,即使我們并不需要擔(dān)憂延遲的插入。

首先,依賴(lài)同步的插入意味著 appendTo 的調(diào)用者要來(lái)觸發(fā)任何需要在附加元素后立 即運(yùn)行的行為。當(dāng)你的應(yīng)用變大后,你會(huì)發(fā)現(xiàn)在許多地方創(chuàng)建相同的視圖,并且需要擔(dān) 心它對(duì)每個(gè)地方的聯(lián)系。

生命周期回調(diào)消滅了實(shí)例化視圖和它的提交插入行為兩部分代碼的耦合。一般地,我們 發(fā)現(xiàn)不依賴(lài)于同步副作用導(dǎo)致了整體上的優(yōu)良設(shè)計(jì)。

第二,因?yàn)殛P(guān)于視圖生命周期的一切都在視圖本身內(nèi)部,按需重渲染 DOM 的部分對(duì) Ember 是非常容易的。

例如,如果這個(gè)按鈕在一個(gè) {{#if}} 塊中,并且 Ember 需要從主分支切換到 else 節(jié),Ember 可以輕易實(shí)例化視圖并調(diào)用生命周期回調(diào)。

因?yàn)?Ember 強(qiáng)迫你定義一個(gè)完整定義的視圖,它可以控制在合適的場(chǎng)合創(chuàng)建并插入視 圖。

這也意味著所有的與 DOM 相關(guān)的代碼只在應(yīng)用中封裝好的幾個(gè)部分,所以 Ember 在 這些在回調(diào)之外的渲染過(guò)程中的部分有更多的自由。

觀察者

在一些罕見(jiàn)的情況,你會(huì)想要在屬性變更已經(jīng)傳播之后執(zhí)行特定的行為。正如前面一節(jié) 中所述,Ember 提供了一個(gè)機(jī)制來(lái)掛鉤到屬性變更通知。

讓我們返回“稱(chēng)呼”的例子。

 
 
 
  1. App.PostController = Ember.ObjectController.extend({ 
  2.   author: function() { 
  3.     return [this.get('salutation'), this.get('name')].join(' '); 
  4.   }.property('salutation', 'name') 
  5. }); 

如果我們想在作者變更時(shí)被通知,我們可以注冊(cè)一個(gè)觀察者。讓我們表示為視圖函數(shù) 想要被通知:

 
 
 
  1. App.PostView = Ember.View.extend({ 
  2.   controller: null, 
  3.   template: Ember.Handlebars.compile("

    {{title}}

    {{author}}

    {{body}}
    "), 
  4.   authorDidChange: function() { 
  5.     alert("New author name: " + this.getPath('controller.author')); 
  6.   }.observes('controller.author') 
  7. }); 

Ember 在它成功傳播變更后觸發(fā)觀察者。在本例中,這意味著 Ember 會(huì)只對(duì)每個(gè)用戶 事件調(diào)用一次 authorDidChange ,即使 salutation 和 name 都有變更。

這為你提供了在屬性變更后執(zhí)行代碼的便利,而不強(qiáng)制所有的屬性變更同步。這基本上 意味著如果你需要對(duì)一個(gè)計(jì)算屬性的變更做一些手動(dòng)工作,你會(huì)得到相同的合并便利, 如同在 Ember 的綁定系統(tǒng)中一樣。

最后,你也可以手動(dòng)注冊(cè)觀察者,在對(duì)象定義之外:

 
 
 
  1. App.PostView = Ember.View.extend({ 
  2.   controller: null, 
  3.   template: Ember.Handlebars.compile("

    {{title}}

    {{author}}

    {{body}}
    "), 
  4.   didInsertElement: function() { 
  5.     this.addObserver('controller.name', function() { 
  6.       alert("New author name: " + this.getPath('controller.author')); 
  7.     }); 
  8.   } 
  9. }); 

盡管如此,當(dāng)你使用對(duì)象定義語(yǔ)法,Ember 會(huì)自動(dòng)在對(duì)象銷(xiāo)毀時(shí)銷(xiāo)毀觀察期。例如,一 個(gè) {{#if}} 語(yǔ)句從真值變?yōu)榧僦?,Ember 銷(xiāo)毀塊內(nèi)定義的所有試圖。作為這個(gè)過(guò)程 的一部分,Ember 也會(huì)斷開(kāi)所有綁定和內(nèi)聯(lián)觀察者。

如果你手動(dòng)定義了一個(gè)觀察者,你需要確保移除了它。一般地,你會(huì)想要在與創(chuàng)建時(shí)相 反的回調(diào)中移除觀察者。在本例中,你會(huì)想要移除 willDestroyElement 的回調(diào)。

 
 
 
  1. App.PostView = Ember.View.extend({ 
  2.   controller: null, 
  3.   template: Ember.Handlebars.compile("

    {{title}}

    {{author}}

    {{body}}
    "), 
  4.   didInsertElement: function() { 
  5.     this.addObserver('controller.name', function() { 
  6.       alert("New author name: " + this.getPath('controller.author')); 
  7.     }); 
  8.   }, 
  9.   willDestroyElement: function() { 
  10.     this.removeObserver('controller.name'); 
  11.   } 
  12. }); 

如果你在 init 方法中添加了觀察者,你會(huì)想要在 willDestroy 回調(diào)中銷(xiāo)毀它。

總而言之,你會(huì)極少用這種方法注冊(cè)一個(gè)手動(dòng)的觀察者。為了保障內(nèi)存管理,我們強(qiáng)烈 建議盡可能把觀察者定義為對(duì)象定義的一部分。

原文鏈接:http://emberjs.torriacg.org/guides/asynchrony/


分享文章:在Ember中處理異步
鏈接URL:http://www.5511xx.com/article/cohgjdi.html