我的问题是关于Knockout中的单击绑定,以及为什么会发生以下行为。我发现这里有很多点击绑定的问题,但不是我描述的行为的具体问题。
我理解在Knockout中,在页面加载时执行带有参数的单击绑定,因为Knockout需要一个引用(对一个函数),所以当它在绑定中遇到函数调用时,它将执行该函数,期望返回的函数引用绑定到该函数。因此,如果我返回对函数的另一个引用,就会在元素单击时执行该函数。
到目前为止还不错,这是有道理的。
为了让我自己看到这一点,我迅速地创建了以下内容:
HTML:
<input data-bind="click: selectImportType(1)" type="button" />
JS
var functiontest = function () {
alert('test');
};
viewModel.selectImportType = function (type) {
viewModel.selectedImport(type);
return functiontest;
}
在执行此操作时,我发现在单击按预期调用functiontest函数时,“functiontest”引用将返回到绑定。
现在让我迷惑不解。我发现在单击元素时也会调用selectImportType函数。首先调用selectImportType,然后调用函数测试函数。
这怎麽可能?绑定期间解析的引用是函数测试函数!
发布于 2016-12-09 10:50:09
当你的写作
data-bind="click: selectImportType(1)"
对表达式selectImportType(1)
进行计算,并返回functiontest
函数,然后将其赋值为单击绑定。
为什么?
因为这是故意的。
当敲除解析绑定时,它会创建绑定字符串计算器,这只是动态函数:
function createBindingsStringEvaluator(bindingsString, options) {
// Build the source for a function that evaluates "expression"
// For each scope variable, add an extra level of "with" nesting
// Example result: with(sc1) { with(sc0) { return (expression) } }
var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString, options),
functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}";
return new Function("$context", "$element", functionBody);
}
就您的情况而言,functionBody是:
"with($context){with($data||{}){return{'click':function(){return selectImportType(1) }}}}"
然后对parsedBindings (https://github.com/knockout/knockout/blob/v3.4.1/src/binding/bindingProvider.js#L27)进行评估,得到这样的结果
{
"click": function(){return selectImportType(1)}
}
它将以下列方式传递给bindginHandler:
var valueAccessor = getValueAccessor(bindingKey);
||
click
所以valueAccessor
是函数:
function(){return selectImportType(1)}
然后让我们看看源代码事件绑定( https://github.com/knockout/knockout/blob/v3.4.1/src/binding/defaultBindings/event.js#L6-L18):
ko.bindingHandlers[eventName] = {
'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var newValueAccessor = function () {
var result = {};
result[eventName] = valueAccessor(); // 1
return result;
};
return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindings, viewModel, bindingContext);
}
}
ko.bindingHandlers['event'] = {
'init' : function (element, valueAccessor, allBindings, viewModel, bindingContext) {
var eventsToHandle = valueAccessor() || {}; // 2
如您所见,valueAccessor
被包装在newValueAccessor
中,当敲除得到单击事件的处理程序时(请参见注释2),newValueAccessor
也会被计算,并得到执行selectImportType(1)
的结果。
最后,eventsToHandle
将成为您的functiontest
function () {
alert('test');
}
这就是为什么在单击按钮时调用functiontest
函数的原因
我猜你在找这样的东西:
data-bind="click: selectImportType.bind($data, 1)"
在这种情况下,只有在单击按钮元素后才会调用selectImportType
函数。
关于如何将参数传递给剔除绑定中的函数,有很多问题。
https://stackoverflow.com/questions/41065597
复制