KnockoutJS虚拟/通配符(*)元素或类似行为?

时间:2014-06-10 17:56:45

标签: javascript knockout.js

想知道是否有任何方法可以将可观察数组绑定到由该数组中的值(对象,数组,字符串,...)定义的元素。例如,如果我有:

var elements = ko.observableArray(['h1','p','blockquote']);

应用viewmodel绑定后,我有一个用于插入每个模板的按钮,我将如何进行模板操作?本能地,我想要类似的东西:

<div id="container" data-bind="foreach: elements">
  <!-- ko html: '<' + $data + '>' + '</' + $data + '>' -->
  <!-- /ko -->
</div>

但是我怀疑,KnockoutJS告诉我:

  

消息:绑定&#39; html&#39;不能与虚拟元素一起使用

解?

4 个答案:

答案 0 :(得分:3)

我认为使用自定义绑定完全可以。

所以我们只需构建一个名为changeTag的绑定:

ko.bindingHandlers.changeTag = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        $(element).replaceWith('<'+bindingContext.$data+'></'+bindingContext.$data+'>');
    },
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {

    }
};

然后将该绑定应用于html。

<div data-bind="foreach: elements">
    <div data-bind="changeTag:{}"><div>
</div>

如果我误解了这个问题,请告诉我,但我认为这就是你想要的。

这是一个小提琴:

http://jsfiddle.net/H5rk6/1/

答案 1 :(得分:2)

从我的评论扩展到您的问题。假设您的数据代表一系列博客文章,每个博客文章都分为几个项目。

var blogData = {
    "title": "My Blog",
    "posts": [
        {
            "title": "First Post",
            "items": [
                {
                    "type": "paragraph",
                    "content": "The first paragraph."
                },
                {
                    "type": "paragraph",
                    "content": "The second paragraph."
                },
                {
                    "type": "quote",
                    "by": "Somebody important",
                    "content": "Quote text"
                }
            ]
        }
    ]
};

您可以使用动态模板,例如:

<h1 data-bind="text: title"></h1>
<div data-bind="foreach: posts">
    <div class="post">
        <h2 data-bind="text: title"></h2>
        <div data-bind="foreach: items">
            <!-- ko template: {name: 'item-' + type} --><!-- /ko -->
        </div>
    </div>
</div>

<script type="text/html" id="item-paragraph">
    <p data-bind="text: content"></p>
</script>
<script type="text/html" id="item-quote">
    <blockquote data-bind="text: content, attr: {title: by}"></blockquote>
</script>

和简单的

ko.applyBindings(blogData);

这样您就可以将实际演示文稿与数据分离。

最小小提琴over here

答案 2 :(得分:1)

您可以使用“ko if”来检查它是什么类型的元素。我知道它有点冗长,但这是我知道做这样的事情的唯一方法。

<!-- ko if: $data == "h1" -->
<h1></h1>
<!-- /ko -->

等。等

或者更确切地说......

<h1 data-bind="if: $data == 'h1'"></h1>
<p data-bind="if: $data == 'p'"></p>
<blockquote data-bind="if: $data == 'blockquote'"></blockquote>

答案 3 :(得分:0)

您可以使用数组的$ data属性。以下是jsfiddle中的类似工作示例:http://jsfiddle.net/wrathchild77/YbLv6/2/

<div data-bind="foreach: elements">
    <h1 data-bind="if: $data == 'h1'">Heading 1</h1>
    <p data-bind="if: $data == 'p'">paragraph</p>
    <blockquote data-bind="if: $data == 'blockquote'">blockquote</blockquote>
</div>

$(function () {
    var baseModel = {
        // data
        elements: ko.observableArray(['h1', 'p', 'blockquote'])
    };

    ko.applyBindings(baseModel);
});