Javascript Knockout.js:更新绑定?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8281875/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
knockout.js: update bindings?
提问by Christian Engel
when I inject any new elements into the DOM after ko.applyBindings(); was called, then knockout won't recognize these new elements. I can understand why this is happening - they are just not indexed by knockout.
当我在 ko.applyBindings() 之后将任何新元素注入 DOM 时;被调用,然后淘汰赛将无法识别这些新元素。我能理解为什么会发生这种情况——他们只是没有被淘汰赛索引。
So, at first I thought this would be solved by just calling ko.applyBindings() again, after adding my new elements, BUT then I realized that for every ko.applyBindings() call you make, the according events get fired multiple times. So after applying five times, a click: binding will be fired five times, so this is not a desireable solution ;)
所以,起初我认为这可以通过再次调用 ko.applyBindings() 来解决,在添加我的新元素之后,但后来我意识到对于你进行的每个 ko.applyBindings() 调用,相应的事件都会被多次触发。所以在应用五次之后,一个 click: binding 将被触发五次,所以这不是一个理想的解决方案;)
Is there anything like ko.updateBindings() or something else, to tell knockout to, well... update the element bindings?
有没有像 ko.updateBindings() 或其他东西,告诉淘汰赛,嗯...更新元素绑定?
greetings, Chris
问候,克里斯
回答by ColinE
Each time you invoke ko.applyBindings
the entire DOM is inspected for bindings. As a result you will get multiple bindings for each element if you do this more than once. If you just want to bind a new DOM element you can pass this element as a parameter to the applyBindings
function:
每次调用ko.applyBindings
整个 DOM 时都会检查绑定。因此,如果您多次执行此操作,您将为每个元素获得多个绑定。如果你只想绑定一个新的 DOM 元素,你可以将此元素作为参数传递给applyBindings
函数:
ko.applyBindings(viewModelA, document.getElementById("newElement"));
See this related question:
看到这个相关的问题:
回答by SamStephens
Without knowing what you're up to exactly, it seems like you're going the wrong way about this. Your view should be driven by your view model. So you shouldn't be directly adding DOM elements you then need to apply knockout bindings to.
在不知道你到底在做什么的情况下,你似乎在这方面走错了路。您的视图应该由您的视图模型驱动。因此,您不应该直接添加 DOM 元素,然后您需要对其应用淘汰赛绑定。
Instead you should be updating your view model to reflect the change in the view, which then causes your new element to appear.
相反,您应该更新您的视图模型以反映视图中的更改,这会导致您的新元素出现。
So for example, for your $('body').append('<a href="#" data-bind="click: something">Click me!</a>');
, rather than adding the DOM element when the button should be visible, control the button visibility using the view model.
因此,例如,对于您的$('body').append('<a href="#" data-bind="click: something">Click me!</a>');
,不要在按钮应该可见时添加 DOM 元素,而是使用视图模型控制按钮的可见性。
So your view model includes
所以你的视图模型包括
var viewModel = { clickMeAvailable: ko.observable(false) }
And your HTML includes
你的 HTML 包括
<a href="#" data-bind="click: something, visible: clickMeAvailable">Click me!</a>
When the application state changes so the click me button is available, you then just viewModel.clickMeAvailable(true)
.
当应用程序状态更改以便单击我按钮可用时,您只需viewModel.clickMeAvailable(true)
.
The point of doing this, and a big part of knockout, is to separate business logic from presentation. So the code that makes click me available doesn't care that click me involves a button. All it does is update viewModel.clickMeAvailable
when click me is available.
这样做的重点,也是淘汰赛的很大一部分,是将业务逻辑与表现分开。因此,使单击我可用的代码并不关心单击我是否涉及按钮。它所做的只是viewModel.clickMeAvailable
在单击我可用时更新。
For example, say click me is a save button that should be available when a form is filled in validly. You'd tie the save button visibility to a formValid
view model observable.
例如,假设单击我是一个保存按钮,当表单被有效填写时应该可用。您可以将保存按钮的可见性与formValid
可观察的视图模型联系起来。
But then you decide to change things so after the form is valid, a legal agreement appears which has to be consented to before saving. The logic of your form doesn't change - it still sets formValid
when the form is valid. You would just change what occurs when formValid
changes.
但随后您决定更改内容,以便在表格有效后,出现必须在保存之前同意的法律协议。表单的逻辑不会改变 -formValid
当表单有效时它仍然会设置。您只需更改更改时formValid
发生的内容。
As lassombra points out in the comments on this answer, there are cases when direct DOM manipulation may be your best approach - for example a complex dynamic page where you only want to hydrate parts of the view as they are needed. But you are giving up some of the separation of concerns Knockout provides by doing this. Be mindful if you are considering making this trade-off.
正如 lassombra 在对此答案的评论中指出的那样,在某些情况下,直接 DOM 操作可能是您的最佳方法 - 例如,在一个复杂的动态页面中,您只想在需要时对视图的一部分进行水合。但是,您通过这样做放弃了 Knockout 提供的一些关注点分离。如果您正在考虑进行这种权衡,请注意。
回答by Maximilian Lindsey
I just stumbled upon a similar problem. I tried to add new elements to container and give those a onclick function.
我只是偶然发现了一个类似的问题。我尝试向容器添加新元素并为它们提供 onclick 功能。
At first tried the things you did, and even tried the approach ColinErecommended. This wasn't a practical solution for me so I tried SamStephensapproach and came up with that, which works perfectly for me:
起初尝试了你所做的事情,甚至尝试了ColinE推荐的方法。这对我来说不是一个实用的解决方案,所以我尝试了SamStephens方法并提出了这个方法,这对我来说非常有效:
HTML:
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:
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>
You can play with it in the JS FiddleI made.
您可以在我制作的JS Fiddle 中使用它。