【问题标题】:knockoutjs - custom template is binded with parent contentknockoutjs - 自定义模板与父内容绑定
【发布时间】:2012-10-31 20:51:13
【问题描述】:

我在使用带有自定义模板绑定的 knockoutjs 时遇到问题。

假设我有一个这样的 HTML 正文:

<div id="1">
    <div data-bind="template:{name: '2', data: data}"></div>
</div>

<div id="2">
    <h3 data-bind="text: caption"></h3>
</div>

JS 代码如下所示:

var ViewModel2 = function () {
    this.caption = ko.observable("Caption");
}

var ViewModel1 = function () {
    this.data = new ViewModel2();
}

ko.applyBindings(new ViewModel1(), document.getElementById("1"));

如果我们测试这段代码,一切都会正常运行;
参见 JSFiddle 示例:http://jsfiddle.net/4eTWW/33/

现在假设我们要进行自定义模板绑定。我们将使用 'templatex' 绑定而不是 'template'。

在 HTML 中我们只需要更改一行:

<div data-bind="templatex:{name: '2', data: data}"></div>

接下来,让我们为 JS 添加自定义模板绑定:

/*Custom binding*/
ko.bindingHandlers.templatex = {
   init: function (element) {
       ko.bindingHandlers.template.init.apply(this, arguments);
   },

   update: ko.bindingHandlers.template.update
}

见:http://jsfiddle.net/4eTWW/35/

但是在这种情况下我们有一个错误,说它在模型中找不到“标题”。

现在让我们将模板 {} 添加到 html 绑定:

<div data-bind="template: {}, templatex:{name: '2', data: data}"></div>

见:http://jsfiddle.net/4eTWW/36/

现在一切正常。

似乎在绑定父 div 时无法确定子 div 是模板。

那么如何在我的自定义模板活页夹中将其标记为模板?

谢谢。

【问题讨论】:

  • 需要返回模板绑定init函数的值。它返回一个名为controlsDescendantBindings 的标志,它告诉KO 你将处理绑定它的孩子。否则,它将继续尝试将子元素与当前数据上下文绑定。

标签: templates knockout.js


【解决方案1】:

你有错误的更新处理程序,改成这个:

ko.bindingHandlers.templatex= {
    init: function(element) {
        // do things
        return ko.bindingHandlers.template.init.apply(this, arguments);
    },

    update: function(element) {
        return ko.bindingHandlers.template.update.apply(this, arguments);
    }
}

这是工作小提琴:http://jsfiddle.net/vyshniakov/4eTWW/39/

【讨论】:

  • 以前的变种也可以,但是需要返回值。
【解决方案2】:

我认为您不能使用自定义绑定来创建新的模板引擎。您需要使用ko.setTemplateEngine() 注册您的自定义引擎。

来自 knockoutjs 来源:

If you want to make a custom template engine,

[1] Inherit from the ko.templateEngine class (like ko.nativeTemplateEngine does)
[2] Override 'renderTemplateSource', supplying a function with this signature:

       function (templateSource, bindingContext, options) {
           // - templateSource.text() is the text of the template you should render
           // - bindingContext.$data is the data you should pass into the template
           //   - you might also want to make bindingContext.$parent, bindingContext.$parents,
           //     and bindingContext.$root available in the template too
           // - options gives you access to any other properties set on "data-bind: { template: options }"
           //
           // Return value: an array of DOM nodes
       }

[3] Override 'createJavaScriptEvaluatorBlock', supplying a function with this signature:

       function (script) {
           // Return value: Whatever syntax means "Evaluate the JavaScript statement 'script' and output the result"
           //               For example, the jquery.tmpl template engine converts 'someScript' to '${ someScript }'
       }

    This is only necessary if you want to allow data-bind attributes to reference arbitrary template variables.
    If you don't want to allow that, you can set the property 'allowTemplateRewriting' to false (like ko.nativeTemplateEngine does)
    and then you don't need to override 'createJavaScriptEvaluatorBlock'.

示例:http://jsfiddle.net/6pStz/(请参阅此 page 的注释 7)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-02
    • 2015-07-27
    相关资源
    最近更新 更多