用于将参数传递给KnockoutJS模板的扩展语法

时间:2012-01-09 18:43:55

标签: knockout.js

我遇到过几种情况,我必须像这样编写模板调用:

<!-- ko template: {name: 'paginatedList', 
                   data: {listContainer: paginatedResults, itemTemplate: $parent.template}} --> 
<!-- /ko -->

因为除了我的数据对象(例如paginatedResults)之外,我还需要传递补充信息,例如用于渲染项目的模板名称。作为另一个示例,当在列表中呈现项目时,我可能需要知道存储在某个上下文中的过滤器的当前设置,该过滤器在逻辑上远离列表中的项目。

而不是必须扭曲我的数据模型(在上面的示例中,将paginatedResults替换为{listContainer: paginatedResults, itemTemplate: $parent.template}},在模板上使用一些语法可以让我传递(和acccrue as templates是分层次计算的)一些深层嵌套模板在渲染时可能需要的额外上下文。

我想我想知道的是在ko.bindingHandlers函数(initupdate)中添加额外(可选)参数的可行性,使它们看起来像这样:

function (element, 
          valueAccessor, 
          allBindingsAccessor, 
          viewModel, 
          bindingContext, 
          context)

在对上面的例子进行编码时,我应该能够说出像

这样的内容
<!-- ko template: {name: 'paginatedList', 
                   data: paginatedResults, 
                   context: {itemTemplate: $parent.template}} --> 
<!-- /ko -->

或更好,

<!-- ko template: {name: 'paginatedList', 
                   data: paginatedResults, 
                   itemTemplate: $parent.template} --> 
<!-- /ko -->

并让itemTemplate成为我可以在嵌套模板和data-bind属性中引用的变量。

这有意义吗?我不太了解这将是多么难以实施。我想要担心的是名称冲突,但是一些命名约定可能会绕过它。

基因

1 个答案:

答案 0 :(得分:9)

如果不对Knockout核心进行更改,我认为您可以做的最好的是包装器绑定,它会创建一个类似于您当前传递的结构。

绑定可能如下所示:

ko.bindingHandlers.templateWithContext = {
    init: ko.bindingHandlers.template.init,
    update: function(element, valueAccessor, allBindings, data, context) {
        var options = ko.utils.unwrapObservable(valueAccessor());

        ko.utils.extend(context, options.context);

        return ko.bindingHandlers.template.update.apply(this, arguments);
    } 
};   

您可以这样称呼:

<div data-bind="templateWithContext: { name: 'itemsTmpl', data: items, context: { title: 'First' } }"></div>

以下是一个示例:http://jsfiddle.net/rniemeyer/QNvFn/

看起来您正在使用本机模板,但如果您仍在使用jQuery模板,那么它确实包含使用jQuery模板的templateOptions功能传递的options feature上下文数据。这在本机模板中不可用。现在的一般建议是使用$root$parent$parents variables来访问信息或将对象作为data传递给你在帖子中描述过。