knockout.js:更新绑定?

时间:2011-11-26 21:46:42

标签: javascript knockout.js

当我在ko.applyBindings()之后将任何新元素注入到DOM中时被召唤,然后淘汰赛将无法识别这些新元素。 我可以理解为什么会这样 - 他们只是没有被淘汰索引。

所以,起初我认为这可以通过再次调用ko.applyBindings()来解决,在添加我的新元素后,然后我意识到,对于你做的每个ko.applyBindings()调用,相应的事件被触发多次。因此,在应用五次后,点击:绑定将被触发五次,因此这不是一个理想的解决方案;)

有什么像ko.updateBindings()或其他东西,告诉敲门,好吧......更新元素绑定?

问候, 克里斯

3 个答案:

答案 0 :(得分:36)

每次调用ko.applyBindings时,都会检查整个DOM是否存在绑定。因此,如果您多次执行此操作,您将获得每个元素的多个绑定。如果您只想绑定一个新的DOM元素,可以将此元素作为参数传递给applyBindings函数:

ko.applyBindings(viewModelA, document.getElementById("newElement"));

请参阅此相关问题:

Can you call ko.applyBindings to bind a partial view?

答案 1 :(得分:7)

如果你不知道自己究竟做了什么,那么你似乎对此有了错误的看法。您的视图应由您的视图模型驱动。所以你不应该直接添加DOM元素,然后你需要将knockout绑定应用到。

相反,您应该更新视图模型以反映视图中的更改,然后导致新元素出现。

例如,对于您的$('body').append('<a href="#" data-bind="click: something">Click me!</a>');,而不是在按钮应该可见时添加DOM元素,使用视图模型控制按钮可见性。

所以你的视图模型包括

var viewModel = { clickMeAvailable: ko.observable(false) }

您的HTML包含

<a href="#" data-bind="click: something, visible: clickMeAvailable">Click me!</a>

当应用程序状态发生变化以便单击“我”按钮可用时,您只需viewModel.clickMeAvailable(true)

这样做以及淘汰的重要部分是将业务逻辑与表示分开。所以点击我可用的代码并不关心点击我涉及一个按钮。当点击我时,它所做的只是更新viewModel.clickMeAvailable

例如,单击“我”是一个保存按钮,在有效填写表单时应该可用。您可以将保存按钮可见性与可观察的formValid视图模型绑定。

但是,在表格有效之后,您决定改变方式,出现一个必须在保存之前同意的法律协议。表单的逻辑不会更改 - 当表单有效时,它仍会设置formValid。您只需更改formValid更改时发生的情况。

正如lassombra在对此答案的评论中指出的那样,有些情况下直接DOM操作可能是您最好的方法 - 例如,复杂的动态页面,您只需要根据需要水合部分视图。但是你放弃了Knockout提供的一些关注点。如果你正在考虑做出这种权衡,请注意。

答案 2 :(得分:0)

我知道你很久以前就问过,但我偶然发现了类似的问题。我尝试将新元素添加到容器中并为其提供onclick功能。 首先尝试了你所做的事情,甚至尝试了方法ColinE recommended。这对我来说不是一个实用的解决方案,所以我尝试了SamStephens方法并提出了这个方法,这对我来说非常有用:

HTML:

<div id="workspace" data-bind="foreach:nodeArr, click:addNode">
<div class="node" data-bind="attr:{id:nodeID},style:{left:nodeX,top:nodeY},text:nodeID, click:$parent.changeColor"></div>
</div>

JavaScript的:

<script>
function ViewModel() {
var self = this;
var id = 0;
self.nodeArr = ko.observableArray();
self.addNode = function (data, event) {
    self.nodeArr.push({
        'nodeID': 'node' + id,
        'nodeX' : (event.offsetX - 25) + 'px',
        'nodeY' : (event.offsetY - 10) + 'px'
    })
    id++;
}
self.changeColor = function(data, event){
    event.stopPropagation();
    event.target.style.color = 'green';
    event.target.style.backgroundColor = 'white';
}
}
ko.applyBindings(new ViewModel());
</script>

你可以在我制作的JS Fiddle中玩它。 希望这仍然有助于某人。