尝试将text
绑定到viewmodel之外的全局函数会引发以下错误:
knockout.js:60未捕获的ReferenceError:无法处理绑定“foreach:function(){return names}” 消息:无法处理绑定“text:function(){return myFunction($ data)}” 消息:myFunction未定义
HTML
<ul data-bind="foreach: names">
<li data-bind="text: myFunction($data)"></li>
</ul>
JS
function myFunction(text){
return text + '--';
}
function demoViewModel() {
self.names = ['a', 'b', 'c'];
return self;
}
var mm = new demoViewModel();
ko.applyBindings(mm);
相反,如果我扩展String
对象并按以下方式应用该函数,它将按预期工作:
<li data-bind="text: $data.myFunction()"></li>
扩展String对象:
String.prototype.myFunction = function(){
return this + '--';
}
这是为什么?是否有更好的方法将全局函数应用于text
绑定?
答案 0 :(得分:1)
这是我建议做你想做的事。您的功能未在该范围内定义。在这里,你实际上将每个名称(甚至它可以是一个对象)绑定到视图模型之外的函数
示例:https://jsfiddle.net/1hz10pkc/2/
HTML:
<ul data-bind="foreach: names">
<li data-bind="text:name "></li>
</ul>
JS
var myFunction = function(text){
var self = this;
self.name = text + "--" ;
}
function demoViewModel() {
var self = this;
var arr = ['a', 'b', 'c'];
self.names = ko.observableArray($.map(arr, function (element) {
return new myFunction(element);
}));
}
var mm = new demoViewModel();
ko.applyBindings(mm);
答案 1 :(得分:1)
要从淘汰模板中引用您的函数,需要将其附加到ViewModel。在上面的简单案例中,您只需将其附加到demoViewModel
并直接在模板中引用它:
function myFunction(text){
return text + '--';
}
function demoViewModel() {
var self = this;
self.names = ['a', 'b', 'c'];
self.myFunction = myFunction;
return self;
}
ko.applyBindings(new demoViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: names">
<li data-bind="text: myFunction($data)"></li>
</ul>
这不是一个真正的“全局”函数,它只是一个标准的viewModel属性,如果您最终使用嵌套绑定上下文,则必须执行$parents[n].myFunction
,或者如果您已将其附加到root viewModel,你可以做$root.myFunction
。
另一种处理方法是直接将函数添加到binding context。无论当前的viewModel是什么,都允许引用它。
“foreach”绑定处理程序和模板绑定处理程序的“as”选项是向绑定上下文添加内容的一种方法;但是为了这个目的,我使用了一个“let”bindingHandler,let bindingHandler不是KO的官方部分,而是Michael Best的often recommended,是其中一个核心贡献者。
function myFunction(text){
return text + '--';
}
function demoViewModel() {
var self = this;
self.names = ['a', 'b', 'c'];
self.myFunction = myFunction;
return self;
}
//Let binding Handler
ko.bindingHandlers['let'] = {
'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
// Make a modified binding context, with extra properties, and apply it to descendant elements
var innerContext = bindingContext.extend(valueAccessor());
ko.applyBindingsToDescendants(innerContext, element);
return { controlsDescendantBindings: true };
}
};
ko.virtualElements.allowedBindings['let'] = true;
ko.applyBindings(new demoViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<!-- ko let: {
myFunction: myFunction
} -->
<ul data-bind="foreach: {
data: names,
at: 'name'
}">
<li data-bind="text: myFunction($data)"></li>
</ul>
<!-- /ko -->
在上面的示例中,您可以在myFunction
绑定中的任何位置引用let
,无论您有多少级别的viewModel。