在淘汰賽很多時候我都在下面的情況:KnockoutJS - 雙向綁定適配器 - 避免循環
我有一個觀察的,我想創造可觀A和B之間的雙向綁定適配器,也就是如果A的變化,改變B和當B的變化,然後改變A.
+-------------+ +-------------+ +-------------+ | A | -----> | Adapter | -----> | B | | Observable | <----- | | <----- | Observable | +-------------+ +-------------+ +-------------+
起初,這似乎是一個不這樣做,因爲這將創建一個循環依賴,但最終這究竟會發生什麼時您將GUI元素綁定到observable。想象一下,你有一個現有的綁定,但你想改變它的綁定結果,而不必觸摸綁定本身。
讓我們看一個例子(jsfiddle here):
HTML:
<body>
<p data-bind="text: 'Value:' + val()"></p>
<input type="text" data-bind="textInput: val"></input>
<p data-bind="text: 'Value 2:' + val2()"></p>
<input type="text" data-bind="textInput: val2"></input>
</body>
的Javascript:
function ViewModel() {
var self = this;
this.val = ko.observable("");
this.val2 = ko.observable("");
this.val.subscribe(function() {
console.log("VAL Changed!");
self.val2(self.val().toUpperCase());
});
this.val2.subscribe(function() {
console.log("VAL2 Changed!");
self.val(self.val2().toLowerCase());
});
}
ko.applyBindings(new ViewModel());
你會發現,當你在輸入的東西第一個文本框一個週期被觸發:
個- 的結合變化VAL
- 的訂閱VAL火災和變化VAL2
- 的訂閱VAL2火災和改變VAL
- 敲除surpresses運行認購VAL再次(週期檢測)
結果是,如果您在第一個輸入框中鍵入一個大寫字母,它將立即轉換爲小寫字母,由第二個訂閱,反之亦然。
雖然這個例子看起來不錯,但它可能會導致很難找到錯誤。要解決現在的問題是一個簡單的方法,有一個標誌裏面的綁定,這將避免升級時,我們是對方的更新裏面:
....
var flag = false;
this.val.subscribe(function() {
if (flag) return;
flag = true;
self.val2(self.val().toUpperCase());
flag = false;
});
this.val2.subscribe(function() {
if (flag) return;
flag = true;
self.val(self.val2().toLowerCase());
flag = false;
});
....
現在當你改變第二個輸入時,它不會「回火」,而只會朝一個方向發射。
現在終於我的問題:
是適配器無效用例和它暗示與代碼的概念問題?
你會如何去防止氣旋?有一個像我的例子中的國旗?也許使用throtteling?
這不能解決循環依賴的影響。如果你運行你的代碼片段,你會意識到,當輸入一個小寫字母到第二個輸入時,它將立即被第一次訂閱反射轉換爲大寫字母。 –
訂閱不做任何轉換。沒有周期。當底層數據項發生變化時,兩個計算的「讀取」值都會改變,就這些了。 –
對不起 - 我沒有花時間理解你的解決方案。所以你說有些情況下,「適配器」的兩端只代表「一個」值。上述解決方案有所不同,它允許適配器的兩端具有不同的狀態,而在您的情況下,適配器的兩端都只依賴一個狀態「val」。這似乎比我更清潔,比馬修斯的解決方案。你認爲有可能出現兩種狀態的解決方案更適用的情況嗎?我的大腦無法完全圍繞它。 –