在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ 高級(jí)的響應(yīng)性
投票
發(fā)布和訂閱
添加用戶
簡(jiǎn)介
會(huì)話
錯(cuò)誤
開始
路由
高級(jí)的響應(yīng)性
編輯帖子
響應(yīng)式
動(dòng)畫
部署
Notifications
允許與拒絕
評(píng)論
創(chuàng)建帖子
非規(guī)范化
高級(jí)發(fā)布機(jī)制
使用 Git 和 GitHub
更進(jìn)一步
延時(shí)補(bǔ)償
集合
分頁(yè)
創(chuàng)建 Meteor Package
模版

高級(jí)的響應(yīng)性

雖然需要你自己寫代碼來(lái)跟蹤依賴變量的情況十分罕見,了解依賴變量的工作流程還是十分必要的。

設(shè)想我們現(xiàn)在需要跟蹤一下 Microscope上,當(dāng)前用戶的 Facebook 朋友在 “l(fā)ike” 某一篇帖子的數(shù)量。 讓我們假設(shè)我們已經(jīng)解決了 Facebook 用戶認(rèn)證的問(wèn)題,運(yùn)用了正確的 API 調(diào)用,而且也解析了相關(guān)數(shù)據(jù)。 我們現(xiàn)在有一個(gè)異步的客戶端函數(shù)返回 like 的數(shù)量,getFacebookLikeCount(user, url, callback)。

需要特別強(qiáng)調(diào)的是要記住這個(gè)函數(shù)是十分 非響應(yīng)式 而且非實(shí)時(shí)的。它發(fā)起一個(gè) HTTP 請(qǐng)求到 Facebook, 得到一些數(shù)據(jù), 然后作為回調(diào)函數(shù)參數(shù)返回給我們的應(yīng)用程序。 但是如果 like 數(shù)改變了而這個(gè)函數(shù)不會(huì)重新運(yùn)行,那么我們的界面上就無(wú)法得到當(dāng)前最新數(shù)據(jù)了。

要解決這個(gè)問(wèn)題,我們首先使用 setInterval 來(lái)每隔幾秒鐘調(diào)用一次這個(gè)函數(shù):

currentLikeCount = 0;
Meteor.setInterval(function() {
  var postId;
  if (Meteor.user() && postId = Session.get('currentPostId')) {
    getFacebookLikeCount(Meteor.user(), Posts.find(postId).url,
    function(err, count) {
      if (!err) {
        currentLikeCount = count;
      }
    });
  }
}, 5 * 1000);

任何時(shí)候當(dāng)我們檢查 currentLikeCount 變量, 我們期望可以得到一個(gè)5秒鐘之內(nèi)準(zhǔn)確的數(shù)據(jù)。我們現(xiàn)在在幫助方法使用這個(gè)變量。代碼如下:

Template.postItem.likeCount = function() {
  return currentLikeCount;
}

然而,我們無(wú)法每次當(dāng)currentLikeCount 改變的時(shí)候重繪模板。盡管變量自己現(xiàn)在可以偽實(shí)時(shí)了,但是它不是響應(yīng)式的所以無(wú)法正確地和 Meteor 生態(tài)環(huán)境中的其他部分進(jìn)行溝通。

Tracking Reactivity: Computations

Meteor 的響應(yīng)性是靠 依賴 來(lái)控制的, 就是一個(gè)跟蹤 Computation 的數(shù)據(jù)結(jié)構(gòu)。

正如我們此前在響應(yīng)式章節(jié)看到的, 一個(gè) computation 是一段代碼用來(lái)處理響應(yīng)式數(shù)據(jù)。我們的例子中有一個(gè) computation 隱式的建立給 postItem 這個(gè)模板用。 這個(gè)模板中的每個(gè)幫助方法都有自己的 computation 。

你可以想象這個(gè) computation 就是一段專門關(guān)注響應(yīng)式數(shù)據(jù)的代碼。 當(dāng)數(shù)據(jù)改變了, 這個(gè) computation 就會(huì)通知 (通過(guò) invalidate()) , 而且也正是 computation 來(lái)決定是否有什么工作需要做。

將變量變?yōu)轫憫?yīng)式函數(shù)

將變量 currentLikeCount 放到一個(gè)響應(yīng)式數(shù)據(jù)源中,我們需要跟蹤所有依賴這個(gè)變量的 computations.這需要把它從變量變?yōu)橐粋€(gè)函數(shù) (有返回值的函數(shù)):

var _currentLikeCount = 0;
var _currentLikeCountListeners = new Tracker.Dependency();

currentLikeCount = function() {
  _currentLikeCountListeners.depend();
  return _currentLikeCount;
}

Meteor.setInterval(function() {
  var postId;
  if (Meteor.user() && postId = Session.get('currentPostId')) {
    getFacebookLikeCount(Meteor.user(), Posts.find(postId),
    function(err, count) {
      if (!err && count !== _currentLikeCount) {
        _currentLikeCount = count;
        _currentLikeCountListeners.changed();
      }
    });
  }
}, 5 * 1000);

我們建立了一個(gè)叫 _currentLikeCountListeners 的依賴,它來(lái)跟蹤所有用到 currentLikeCount() 的 computations. 當(dāng) _currentLikeCount 值發(fā)生變化,我們通過(guò)調(diào)用依賴的 changed() 函數(shù),來(lái)通知所有 computations 數(shù)據(jù)變化了。

這些 computations 可以繼續(xù)處理下面的數(shù)據(jù)變化。

你可能覺(jué)得這像是在響應(yīng)式數(shù)據(jù)源上的很多引用,你說(shuō)對(duì)了,Meteor 提供很多工具使這項(xiàng)工作簡(jiǎn)單 (你不需要直接調(diào)用 computations , 他們會(huì)自動(dòng)運(yùn)行)。有一個(gè)叫做 reactive-var 的包,它的內(nèi)容正是函數(shù) currentLikeCount() 要做的事。我們加入這個(gè)包:

meteor add reactive-var

使用它可使我們的代碼簡(jiǎn)化一點(diǎn):

var currentLikeCount = new ReactiveVar();

Meteor.setInterval(function() {
  var postId;
  if (Meteor.user() && postId = Session.get('currentPostId')) {
    getFacebookLikeCount(Meteor.user(), Posts.find(postId),
    function(err, count) {
      if (!err) {
        currentLikeCount.set(count);
      }
    });
  }
}, 5 * 1000);

現(xiàn)在使用這個(gè)包,我們?cè)趲椭椒ㄖ姓{(diào)用 currentLikeCount.get(),它會(huì)像之前一樣工作。有另外一個(gè)有用的包 reactive-dict, 它提供 key-value 存儲(chǔ) (像 Session 一樣)。

Comparing Tracker to Angular

Angular 是一個(gè)客戶端響應(yīng)式庫(kù),是 Google 的家伙們開發(fā)的。我們來(lái)比較 Meteor 和 Angular 的依賴跟蹤方式。他們的實(shí)現(xiàn)方式非常不同。

我們已經(jīng)知道 Meteor 使用一些被稱為 comptations 的代碼來(lái)實(shí)現(xiàn)依賴跟蹤的。這些 computations 被特殊的 "響應(yīng)式" 數(shù)據(jù)源(函數(shù))跟蹤,在數(shù)據(jù)變化的時(shí)候?qū)⑺麄冏约簶?biāo)記為 invalidate。當(dāng)需要調(diào)用 invalidate() 函數(shù)時(shí),響應(yīng)式數(shù)據(jù)源_顯示的_通知所有依賴。請(qǐng)注意這是數(shù)據(jù)變化時(shí)的一般情況,數(shù)據(jù)源也可以因?yàn)槠渌蛴|發(fā) invalidation。

另外,盡管通常情況下當(dāng)數(shù)據(jù) invalidate 時(shí) computations 只是重新運(yùn)行,但是你也可以在此時(shí)指定任何你想要的行為。這些給了用戶很高的響應(yīng)式控制權(quán)。

在 Angular 中,響應(yīng)式是通過(guò) scope 對(duì)象來(lái)調(diào)節(jié)的。一個(gè) scope 可以看做是擁有一些特殊方法的普通 js 對(duì)象。

當(dāng)你的響應(yīng)式數(shù)據(jù)依賴于 scope 中的一個(gè)值,你調(diào)用 scope.$watch 方法,告訴 expression 你關(guān)心的數(shù)據(jù)(例如: 你關(guān)心 scope 中的哪些數(shù)據(jù))和一個(gè)當(dāng) expression 發(fā)生變化時(shí)每次都運(yùn)行的監(jiān)聽器。因此你需要顯示的提供當(dāng) expression 數(shù)據(jù)變化時(shí)你要做的操作。

回到之前 Facebook 的例子,我們的代碼可以寫成如下:

$rootScope.$watch('currentLikeCount', function(likeCount) {
  console.log('Current like count is ' + likeCount);
});

當(dāng)然,就像在 Meteor 中你很少需要去建立 computations, 在 Angular 中你無(wú)須經(jīng)常顯示調(diào)用 $watch, ng-model{{expressions}} 會(huì)自動(dòng)建立跟蹤,之后當(dāng)數(shù)據(jù)變化時(shí)他們會(huì)處理重新展示的事情。

當(dāng)響應(yīng)式數(shù)據(jù)發(fā)生變化時(shí), scope.$apply() 方法會(huì)被調(diào)用。他會(huì)重新計(jì)算 scope 中所有的 watcher, 然后只調(diào)用 expression 值發(fā)生變化的 watcher 的監(jiān)聽器方法。

因此 scope.$apply() 方法和 Meteor 中的 dependency.changed() 很相似,除了它是在 scope 級(jí)別操作,而不是給你控制權(quán)決定哪個(gè) listener 需要重新 evaluate。換句話說(shuō),較少的控制使得 Angular 可以通過(guò)聰明和高效的方式來(lái)決定哪些 listener 需要重新 evaluate。

在 Angular 中,我們的 getFacebookLikeCount() 函數(shù)看起來(lái)如下:

Meteor.setInterval(function() {
  getFacebookLikeCount(Meteor.user(), Posts.find(postId),
  function(err, count) {
    if (!err) {
      $rootScope.currentLikeCount = count;
      $rootScope.$apply();
    }
  });
}, 5 * 1000);

必須承認(rèn),Meteor 替我們完成了響應(yīng)式的大部分繁重工作,但是希望,通過(guò)這些模式的學(xué)習(xí),可以對(duì)你的深入研究起到幫助。