2016-06-16 55 views
1

隨着調試JS代碼中綁定定義如下爲什麼KO不是基於表達式創建觀察值?

<div data-bind="myBinding: { ... }, enable: isEnable() && isThatEnabled()"></div> 

,當我看着在myBinding的init的allBindings其定義像一般:

init: function (element, valueAccessor, allBindings, viewModel, bindingContext) 

我看到allBindings.enable是一個布爾值,這是isEnable() && isThatEnabled()的實際計算值。這不是像我預期的基於布爾表達式創建的可觀察值。

我的問題是爲什麼它不是一個可觀察的?

在這種情況下是否可以從myBinding觀察「啓用」綁定?

我看到3個選項:

  1. 定義自定義enable結合:

    <div data-bind="myBinding: { ... }, myEnable: isEnable() && isThatEnabled()"></div>

  2. myBinding一個 '啓用' 參數:

    <div data-bind="myBinding: { enable: isEnable() && isThatEnabled() }"></div>

  3. 使用計算觀察到在HTML:

    data-bind="myBinding: bar, enable: ko.computed(function() { return foo() && foo2(); })"

第二屆一個似乎最合理的給我。

var model = { 
 
    foo: ko.observable(true), 
 
    foo2: ko.observable(true), 
 
    bar: ko.observable(1) 
 
}; 
 

 
ko.bindingHandlers.myBinding = { 
 
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { 
 
    var value = valueAccessor(); 
 
    var valueUnwrapped = ko.unwrap(value); 
 
     
 
    element.innerHTML += ko.isObservable(allBindings().enable); 
 
    
 
    // how unfortunate, 'enable' binding value is not observable 
 
    // how to listen to 'enable' binding changes right here? 
 
    }, 
 

 
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) { 
 
    var value = valueAccessor(); 
 
    var valueUnwrapped = ko.unwrap(value); 
 
    } 
 
}; 
 

 
function onload() { 
 
    ko.applyBindings(model); 
 
}
<!DOCTYPE html> 
 
<html> 
 
<head> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script> 
 
    <meta charset="utf-8"> 
 
    <meta name="viewport" content="width=device-width"> 
 
    <title>JS Bin</title> 
 
</head> 
 
<body onload="onload()"> 
 
    <input type="checkbox" data-bind="checked: foo"> 
 
    <input type="checkbox" data-bind="checked: foo2"> 
 
    <button data-bind="myBinding: bar, enable: foo() && foo2()">Is 'enable' binding observable: </button> 
 
</body> 
 
</html>

+0

你使用哪個版本的'ko'?我不能用'ko-3.3.0'重現這個。出乎意料的是,即使使用普通的js函數!我的沙箱:http://jsbin.com/cituzifuca/edit –

回答

1

從Ko來源:

// Use of allBindings as a function is maintained for backwards compatibility, but its use is deprecated 
function allBindings() { 
    return ko.utils.objectMap(bindingsUpdater ? bindingsUpdater() : bindings, evaluateValueAccessor); 
} 
// The following is the 3.x allBindings API 
allBindings['get'] = function(key) { 
    return bindings[key] && evaluateValueAccessor(getValueAccessor(key)); 
}; 
allBindings['has'] = function(key) { 
    return key in bindings; 
}; 

如果你打電話allBindings()它解開所有綁定的值。因此,如果您從計算函數訪問它(例如從綁定的update方法),則計算的函數將訂閱所有綁定更改的更新。

您不能訪問直接觀察到的,但你可以ko.computed包裝它:

var enableObs = ko.computed(function() {return allBindings().enable;}); 

注:使用allBindings 作爲功能已經過時!因爲如果你從update方法調用它,它將在其他綁定中的任何更新上執行。所以,最好是:

var enableObs = ko.computed(function() {return allBindings.get('enable');}); 

見的myBindingmyBinding2行爲的差異。 另外,您也可以訂閱update方法(無計算)的更新(myBinding3)。

var model = { 
 
    foo: ko.observable(true), 
 
    foo2: ko.observable(true), 
 
    text: ko.observable("changeme"), 
 
    log: ko.observableArray([]) 
 
}; 
 

 
ko.bindingHandlers.myBinding = { 
 
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { 
 
    var value = valueAccessor(); 
 
    var num=0; 
 
    var valueUnwrapped = ko.unwrap(value); 
 
     
 
    var enableObs = ko.computed(function() { 
 
     // Note this computed executes on update of any binding. Not only for `enable` binding. Increment for show it. 
 
     return allBindings().enable.toString() + num++; 
 
    }); 
 
    enableObs.subscribe(function() { 
 
     // if you remove counter from computed function this function will execute only on `enable` binding updates. 
 
     element.innerHTML = ko.unwrap(enableObs).toString(); 
 
    }); 
 
    } 
 
}; 
 

 
ko.bindingHandlers.myBinding2 = { 
 
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { 
 
    var value = valueAccessor(); 
 
    var num=0; 
 
    var valueUnwrapped = ko.unwrap(value); 
 
     
 
    var enableObs = ko.computed(function() { 
 
     return allBindings.get("enable").toString() + num++; 
 
    }); 
 
    enableObs.subscribe(function() { 
 
     element.innerHTML = ko.unwrap(enableObs).toString(); 
 
    }); 
 
    } 
 
}; 
 

 
var tmp = 0; 
 
ko.bindingHandlers.myBinding3 = { 
 
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {  
 
     element.innerHTML = allBindings.get('enable').toString() + tmp++; 
 
    } 
 
}; 
 

 
function onload() { 
 
    ko.applyBindings(model); 
 
}
<!DOCTYPE html> 
 
<html> 
 
<head> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script> 
 
    <meta charset="utf-8"> 
 
    <meta name="viewport" content="width=device-width"> 
 
    <title>JS Bin</title> 
 
</head> 
 
<body onload="onload()"> 
 
    <input type="text" data-bind="value: text, valueUpdate: 'keyup'"> 
 
    <input type="checkbox" data-bind="checked: foo"> 
 
    <input type="checkbox" data-bind="checked: foo2"> 
 
    <button data-bind="myBinding, enable: foo() && foo2(), value: text()">Do smth</button> 
 
    <button data-bind="myBinding2, enable: foo() && foo2(), value: text()">Do smth</button> 
 
    <button data-bind="myBinding3, enable: foo() && foo2(), value: text()">Do smth</button> 
 
</body> 
 
</html>


OLD:

init: function (element, valueAccessor, allBindings, viewModel, bindingContext) 

如果你想訂閱 - 使用update函數。 見例如:http://jsbin.com/foxezidada/edit

和文檔:http://knockoutjs.com/documentation/custom-bindings.html

我的問題是,爲什麼是不是可觀察到的?

https://github.com/knockout/knockout/blob/master/src/binding/bindingAttributeSyntax.js

var getValueAccessor = bindingsUpdater 
    ? function(bindingKey) { 
     return function() { 
      return evaluateValueAccessor(bindingsUpdater()[bindingKey]); 
     }; 
    } : function(bindingKey) { 
     return bindings[bindingKey]; 
    }; 

它演算值爲這裏。

+0

感謝您的回覆。也許我不清楚我的問題?請看我的例子。我正在研究觀察自定義綁定中的「啓用」綁定。這可能嗎? –

+0

@DonBox答案已更新。 –