[英]What's the secret to data-binding?
對於大多數JS框架和庫,它們帶來的價值通常以新結構的形式出現,如如何構建應用程序(Backbone,React),有效增強語言功能的新想法(Angular),或者僅僅是他們提供的方法已經過測試,快速且非常方便(jQuery)。
通常,他們提供的想法和方法都是JavaScript的簡單明了的用法,但是背后有一個非常聰明的團隊,他們找到有趣的方式來做事情,您可以仔細考慮並就膽量的工作方式做出可靠的猜測。
但是,我一直無法考慮通過雙向綁定JS模型來查看組件的能力。 使此功能起作用的這個功能的核心秘訣是什么? 從用戶輸入更改內部變量很簡單,但是相反呢? 您如何才能“知道” JS變量已更改以便立即更新顯示? 當然不能進行輪詢,那又如何呢?
每當您的JS塊運行該角度觸發時,當該塊完成執行時,它將運行摘要循環。 基本上,這會檢查所有可能更改的值,並且需要更新視圖。
如果angular沒有觸發代碼,那么它將不會知道可能有所更改,因此您的綁定可能會不同步。 例如,如果您運行類似的內容
setTimeout(function() {$scope.myValue = '123'});
Angular不會知道myValue
更改,並且它實際上不會更新視圖。 這就是為什么Angular擁有自己的服務來做所有事情的原因。 例如$timeout
或$http
。
如果您有一些Angular不知道的回調函數,則可以通過調用$scope.$apply()
手動告訴它檢查更改$scope.$apply()
有幾種方法可以做到這一點。 Object.observe很棒,但是缺乏良好的支持。 您也可以輪詢值,並保留對象的第二個副本進行比較。 您還可以編寫自己的顯式set / get方法來更新模型,就像骨干網一樣。
我經常使用的一種整潔方法是使用getters / setter方法來使模型與dom保持同步:
//a demo "model" of data:
model = {
name: "Fred"
};
function change(k,v){alert([k,v]);} // a stand-in change monitor for demo
// iterate model and replace values with getter/setter combos:
Object.keys(model).forEach(function(key) {
var val = model[key];
delete model[key];
Object.defineProperty(model, key, {
get: function() {
return val;
},
set: function(v) {
val = v;
change(key, val);
} //call change upon setting
});
change(key, val); //update view "onload"
}); // alerts "Fred";
//update model (fires change() with "name" and "sally" arguments:
model.name="sally"; // alerts "sally";
更改功能非常簡單,對於您的情況,應該只查找綁定到鍵的元素。 這樣做的好處是您不需要特殊的自定義CRUD方法,可以像1999一樣通過賦值來修改對象屬性。它也不會輪詢,並且可以正常工作到IE9和任何其他ES5環境。 這是不使用自定義方法來綁定JS> DOM(afaik)的最簡單方法。
它確實有一些限制:嵌套對象很難獲取/設置,不能一次完成整個對象,只能“觀察”原始對象。 數組也是一個問題:您不能真正使用沒有副作用的getter / setter替換expando屬性。 但是,在相對平坦地收集JSON安全數據的情況下,get / set很有魅力,並且不需要復雜的庫即可進行操作。
使用此方法簽出完整示例: http : //pagedemos.com/xg3szbguqnwu/4
我可以說說Backbone是如何完成的,Backbone對數據綁定的看法相對較低。
它是1.可以控制屬性設置器方法的庫的組合2.當屬性更改(例如,通過調度事件)時調用回調函數以更新UI。
基本的偽代碼是這樣的:
class Model:
method set(name, value):
if value != this.attributes[name]
this.triggerEvent('change', name, value)
this.attributes[name] = value
m = new Model()
someInputWidget.onEvent('userChangedInput', function(value) {
m.set(someInputWidget.name, value)
})
m.onEvent('change', function(name, value) {
getInputWidgetByName(name).setValue(value)
})
Backbone不會對UI進行任何數據綁定,但是您可以參考Backbone的帶注釋的源來獲取實際的事件調度實現。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.