knockout.js模板中的唯一ID

Rom*_*aev 23 client-side-templating knockout.js

假设我有这样的knockout.js模板:

<script type="text/html" id="mytemplate">
    <label for="inputId">Label for input</label>
    <input type="text" id="inputId" data-bind="value: inputValue"/>
</script>
Run Code Online (Sandbox Code Playgroud)

如果我呈现我最终用相同的ID(和几个标签使用相同的多个输入页面上的几个地方此模板值),其中有不好的后果.特别是,依赖于id的所有代码可能无法正常工作(在我的情况下,我使用的jquery.infieldlabel插件会被具有相同id的多个输入混淆).我现在解决这个问题的方法是将唯一的id属性添加到我绑定到模板的模型中:

<script type="text/html" id="mytemplate">
    <label data-bind="attr: {for: id}>Label for input</label>
    <input type="text" data-bind="attr: {id: id}, value: inputValue"/>
</script>
Run Code Online (Sandbox Code Playgroud)

这可行,但它不是很优雅,因为我必须在我的模型中使用这个人工id属性,而不是用于其他任何东西.我想知道这里是否有更好的解决方案.

RP *_*yer 62

不依赖于字段绑定顺序的替代方法是将绑定设置id为数据本身的属性,这需要是可观察的.

ko.bindingHandlers.uniqueId = {
    init: function(element, valueAccessor) {
        var value = valueAccessor();
        value.id = value.id || ko.bindingHandlers.uniqueId.prefix + (++ko.bindingHandlers.uniqueId.counter);

        element.id = value.id;
    },
    counter: 0,
    prefix: "unique"
};

ko.bindingHandlers.uniqueFor = {
    init: function(element, valueAccessor) {
        var value = valueAccessor();
        value.id = value.id || ko.bindingHandlers.uniqueId.prefix + (++ko.bindingHandlers.uniqueId.counter);

        element.setAttribute("for", value.id);
    } 
};
Run Code Online (Sandbox Code Playgroud)

您会像以下一样使用它:

<ul data-bind="foreach: items">
    <li>
        <label data-bind="uniqueFor: name">Before</label>
        <input data-bind="uniqueId: name, value: name" />
        <label data-bind="uniqueFor: name">After</label>
    </li>
</ul>
Run Code Online (Sandbox Code Playgroud)

示例:http://jsfiddle.net/rniemeyer/JjBhY/

向可观察函数添加属性的好处是,当您将其转换为JSON以发送回服务器时,它将自然消失,因为observable将变为其未包装的值.

  • 我同意那个.但是我可以激怒并就问题的稍微复杂的变体寻求建议 - 你有一对无线电,例如"是"和"否"作为标签,每个都绑定回一个布尔可观察,例如"活跃".目前,所有4个元素 - 2个无线电和2个标签 - 都获得相同的ID.这对无线电本身会出现多次,因此我使用Knockout绑定为每对产生一个唯一的名称属性,因此我需要能够将当前对的特定名称添加到ID之前. (4认同)

RP *_*yer 6

我过去做过类似的事情:

ko.bindingHandlers.uniqueId = {
    init: function(element) {
        element.id = ko.bindingHandlers.uniqueId.prefix + (++ko.bindingHandlers.uniqueId.counter);
    },
    counter: 0,
    prefix: "unique"
};

ko.bindingHandlers.uniqueFor = {
    init: function(element, valueAccessor) {
        var after = ko.bindingHandlers.uniqueId.counter + (ko.utils.unwrapObservable(valueAccessor()) === "after" ? 0 : 1);
          element.setAttribute("for", ko.bindingHandlers.uniqueId.prefix + after);
    } 
};
Run Code Online (Sandbox Code Playgroud)

您可以使用它们:

<ul data-bind="foreach: items">
    <li>
        <label data-bind="uniqueFor: 'before'">Before</label>
        <input data-bind="uniqueId: true, value: name" />
        <label data-bind="uniqueFor: 'after'">After</label>
    </li>
</ul>
Run Code Online (Sandbox Code Playgroud)

因此,它只是保持绑定本身的状态递增ko.bindingHandlers.uniqueId.counter.然后,uniqueFor绑定只需要知道它是在字段之前还是之后知道如何获得正确的id.

此处示例:http://jsfiddle.net/rniemeyer/8KJD3/

如果您的标签不在他们的字段附近(在每个标签之前绑定的多个输入可能在表的不同行中),那么您需要查看不同的策略.