成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

在 Ember 中處理異步

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

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

沒有 Ember 的情況

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

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

  1. jQuery.getJSON('/posts/1'function(post) { 
  2.   $("#post").html("<h1>" + post.title + "</h1>" + 
  3.     "<div>" + post.body + "</div>"); 
  4. }); 

在純 jQuery 應(yīng)用中,你會用這個回調(diào)來隨意進行要更改到 DOM 的更改。

當使用一個基于事件的 MVC 框架,會把邏輯從回調(diào)中拿出而放進模型和視圖對象里。 這改進了很多東西,但仍未擺脫顯式處理異步回調(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("<h1><%= title %></h1><h2><%= author %></h2><div><%= body %></div>"), 
  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. }); 

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

Ember 的方法

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

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

你一般會為這個例子使用用 ember-data ,當讓我們看看如何用 jQuery 來為 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("<h1>{{title}}</h1><h2>{{author}}</h2><div>{{body}}</div>"
  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 的實現(xiàn)方法消滅了當 post 的屬性變更時顯式注冊觀察者 的需求。

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

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

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

益處

因為 Ember 經(jīng)常負責傳播變更,它可以保證在響應(yīng)每個用戶事件上一個變更只傳播一 次。

讓我們再看一看 author 計算屬性。

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

因為我們已經(jīng)指定了它依賴于 salutation 和 name ,這兩個依賴的任何一個的變 更都會使屬性無效,這會觸發(fā)對 DOM 中 {{author}} 的更新。

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

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

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

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

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

當你對 Ember 中的一個屬性做出更改,它不會立即傳播變更。除此之外,它立即無效 任何有依賴的屬性,但把實際的修改放入隊列來讓它在之后發(fā)生。

對 salutation 和 name 屬性都修改會無效 author 屬性兩次,但隊列會智能地 合并那些變更。

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

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

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

副作用回調(diào)

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

例如,想象你有一個包含一個按鈕的視圖,并且你想用 jQuery UI 來樣式化這個按 鈕。因為視圖的 append 方法,如同 Ember 中的其它東西,推遲了它的副作用,怎 樣在正確的時間執(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 會觸發(fā) didInsertElement 回 調(diào),然后你可以做任何你想要做的工作。

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

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

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

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

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

因為 Ember 強迫你定義一個完整定義的視圖,它可以控制在合適的場合創(chuàng)建并插入視 圖。

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

觀察者

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

讓我們返回“稱呼”的例子。

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

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

  1. App.PostView = Ember.View.extend({ 
  2.   controller: null
  3.   template: Ember.Handlebars.compile("<h1>{{title}}</h1><h2>{{author}}</h2><div>{{body}}</div>"), 
  4.   authorDidChange: function() { 
  5.     alert("New author name: " + this.getPath('controller.author')); 
  6.   }.observes('controller.author'
  7. }); 

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

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

最后,你也可以手動注冊觀察者,在對象定義之外:

  1. App.PostView = Ember.View.extend({ 
  2.   controller: null
  3.   template: Ember.Handlebars.compile("<h1>{{title}}</h1><h2>{{author}}</h2><div>{{body}}</div>"), 
  4.   didInsertElement: function() { 
  5.     this.addObserver('controller.name'function() { 
  6.       alert("New author name: " + this.getPath('controller.author')); 
  7.     }); 
  8.   } 
  9. }); 

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

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

  1. App.PostView = Ember.View.extend({ 
  2.   controller: null
  3.   template: Ember.Handlebars.compile("<h1>{{title}}</h1><h2>{{author}}</h2><div>{{body}}</div>"), 
  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 方法中添加了觀察者,你會想要在 willDestroy 回調(diào)中銷毀它。

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

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

責任編輯:陳四芳 來源: emberjs.torriacg.org
相關(guān)推薦

2013-12-25 09:53:22

Ember.js應(yīng)用

2017-08-28 15:21:29

異步處理回調(diào)函數(shù)異步編程

2013-12-24 11:11:27

ember.jsJavascript

2013-12-24 15:56:20

2023-05-04 07:43:47

MySQL數(shù)據(jù)庫

2009-07-07 09:41:02

異步ServletAJAX

2009-08-21 10:43:19

FlyTcpFrame

2013-12-24 16:03:26

Ember.js視圖

2020-03-29 08:27:05

Promise異步編程前端

2013-12-24 13:20:28

EmberEmber.js

2010-12-01 14:34:59

AsyncTask異步處理任務(wù)Android

2015-03-09 09:44:35

GmailiOS

2023-10-28 16:30:19

Golang開發(fā)

2024-01-07 16:46:19

FiberHTTPWeb

2022-04-29 07:35:49

SpringMVC構(gòu)造函數(shù)

2022-01-08 19:00:09

NumPyPython編程語言

2014-07-22 09:01:53

SwiftJSON

2013-05-30 15:16:26

javaScriptMVC模式

2023-11-06 08:01:09

Go同步異步

2020-04-07 00:10:16

javascrip語言異步
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 欧洲av在线 | 亚洲一区二区三区在线播放 | 国产福利一区二区 | 亚洲欧洲日韩精品 中文字幕 | 免费观看的av毛片的网站 | 最新中文字幕一区 | 午夜天堂精品久久久久 | 中文字幕免费视频 | 日韩欧美一级精品久久 | 日本电影免费完整观看 | 欧美精品v| 黄网站涩免费蜜桃网站 | 亚洲国产成人精品女人久久久野战 | 美女一级a毛片免费观看97 | 久久精品欧美一区二区三区不卡 | 国产亚洲精品精品国产亚洲综合 | 日皮视频免费 | 欧美久久久久 | 亚洲精品乱码久久久久久9色 | 亚洲福利视频一区二区 | 亚洲国产精品久久久久秋霞不卡 | 国产高清视频在线 | 欧美性大战久久久久久久蜜臀 | 黄色片网此| 色婷婷av一区二区三区软件 | 自拍 亚洲 欧美 老师 丝袜 | 日韩在线观看中文字幕 | 久久久精 | 91九色在线观看 | 亚洲精品中文字幕 | 欧美激情在线一区二区三区 | 中文字幕av一区 | 国内91在线| 黄色一级大片在线免费看产 | 国产日韩欧美在线观看 | 亚洲欧美综合精品久久成人 | 在线亚洲免费视频 | 特黄av| 午夜爽爽爽男女免费观看影院 | 亚洲精品视频观看 | 欧美一级免费看 |