2013-02-25 133 views
2

上绑定我现在用的是淘汰赛JS模板绑定功能,以使项目集合到一个元素:删除淘汰赛JS克隆元素

<script type="text/javascript"> 
    ko.applyBindings(new function() { 
     this.childItems = [{ Text: "Test", ImageUrl: "Images/Image.png" }]; 
    }); 
</script> 

<script type="text/html" id="template"> 
    <div class="childItem" data-bind="attr: { title: Text }"> 
     <img data-bind="attr: { src: ImageUrl }" /> 
    </div> 
</script> 

<div class="childSelector" data-bind="template: { name: 'template', foreach: childItems }"> 
</div> 

点击时,孩子的物品被克隆并放置到另一个元素:

$(".childSelector").on("click", ".childItem", function() { 
    var clone = $(this).clone()[0]; 
    ko.cleanNode(clone); 
    $(".targetNode").append(clone); 
}); 

的问题是,当源数据变化和模板重新绑定到新的数据,下面的错误被抛出:

Uncaught Error: Unable to parse bindings. Message: ReferenceError: Text is not defined; Bindings value: attr: { title: Text }

我发现了另一篇文章,建议使用ko.cleanNode(element)删除淘汰赛的绑定,但是这并没有解决我的问题。

有没有办法删除克隆元素上的敲除绑定,以防止重新绑定时出现此错误?如果没有,我只需通过从单击元素中提取所需数据来“手动”克隆元素。

Here是我在做

回答

3

您可以通过遍历DOM和移除data-bind属性移除一个元素都淘汰赛绑定和基因敲除的意见。

使用removeDataBindings(clone);但首先用ko.cleanNode(clone)清理节点以清除任何事件处理程序。

var commentNodesHaveTextProperty = document.createComment("test").text === "<!--test-->"; 
var startCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*-->$/ : /^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/; 
var endCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*\/ko\s*-->$/ : /^\s*\/ko\s*$/; 

function isStartComment(node) { 
    return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(startCommentRegex); 
} 

function isEndComment(node) { 
    return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(endCommentRegex); 
} 

function traverseNode(node, func) { 
    func(node); 
    node = node.firstChild; 
    while (node) { 
     traverseNode(node, func); 
     node = node.nextSibling; 
    } 
} 

function removeDataBindings(element) { 
    var koComments = []; 

    traverseNode(element, function (node) { 
     if (isStartComment(node) || isEndComment(node)) { 
      koComments.push(node); 
      return; 
     } 
     //remove the 'data-bind' attributes 
     if (node.nodeType === 1) { //ELEMENT_NODE 
      node.removeAttribute('data-bind'); 
     } 
    }); 

    //remove Knockout binding comments 
    for (i = 0; i < koComments.length; i++) { 
     node = koComments[i]; 
     if (node.parentNode) { 
      node.parentNode.removeChild(node); 
     } 
    } 
} 
+0

感谢你们,我接受了建议,并没有按照我原来的路线走,但是这为未来的访问者回答了问题! – Oliver 2013-02-27 17:11:40

0

什么奥利弗,使用jQuery克隆绑定到淘汰赛单元这样一个简单的例子是不是一个好主意。你应该使用targetNode的数据绑定。如果您还没有这样做,最好通过Knockout Tutorials来了解基本用途。

如果您尝试使用克隆按钮来保留项目列表,这里使用的是dead simple fiddle,但它只使用Knockout来执行此操作。如果你正在尝试做其他事情,请告诉我。你的问题并不完全清楚你的目标。

HTML:

<div data-bind="foreach: items"> 
    <span data-bind="text: $data"></span> 
    <button data-bind="click: $parent.clone">Clone</button></br> 
</div> 

JS:

var ViewModel = function(data) { 
    var self = this; 
    self.items = ko.observableArray(data); 
    self.clone = function(item) { 
     //The ko.toJS here is a handy copy tool for viewModels 
     //It isn't necessary for simple arrays like this one 
     //But I included it because for an array of objects, you will want to use it 
     self.items.push(ko.toJS(item)); 
    }; 
}; 
+0

您好Tyrsius,请参阅我的问题的示例,在执行克隆后重新应用绑定时,会在控制台中引发错误。这是我第一次使用淘汰赛,但是考虑一下,我可以将目标作为可观察数组而不是克隆源项目......你知道是否有关于删除绑定的问题的答案? – Oliver 2013-02-25 23:45:16

+0

我看到错误,你读了我的答案吗?如果您正在使用Knockout,则不应将jQuery用于DOM克隆。该角色属于Knockout。 – Tyrsius 2013-02-25 23:47:47

+0

我做过了,请参阅上面的评论,谢谢。 – Oliver 2013-02-25 23:49:18