问题
For some reason the below code makes the links' click event fire twice. I'm relatively new to knockout and I think I might have done my custom binding wrong. Can anyone tell me what I've done wrong? (Btw, the reason I didn't post a fiddle is that I can't include the mapping plugin from github on jsfiddle.)
JS:
ko.bindingHandlers.activityContent = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
// This will be called when the binding is first applied to an element
// Set up any initial state, event handlers, etc. here
var content = document.createElement("p");
content.innerHTML = '<a href="javascript:void(0)" data-bind="text: user_name, click: $parent.NavigatePage.bind($data, \'profile\', user_id)"></a>';
element.appendChild(content);
ko.applyBindings(bindingContext, content);
},
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
// This will be called once when the binding is first applied to an element,
// and again whenever the associated observable changes value.
// Update the DOM element based on the supplied values here.
}
};
var activities = ko.mapping.fromJS({Activities: [{
"user_id": "52b5042d572b94ceadf6asdf1a2a5bc",
"user_name": "Sean Templeton"
}, {
"user_id": "52b5042d57asfda2b94ce61a2a5bc",
"user_name": "Sean Templeton"
}, {
"user_id": "52b5042d572b94ce61a2a5bc",
"user_name": "Sean Templeton"
}, {
"user_id": "52b5042d5asdfasdf72b94ce61a2a5bc",
"user_name": "Sean Templeton"
}, {
"user_id": "52basdf5042d572b94ce6asdf1a2a5bc",
"user_name": "Sean Templeton"
}], NavigatePage: function(page, userId) { console.log(this); console.log(page); console.log(userId()); }});
ko.applyBindings(activities);
html:
<Ul data-bind="foreach: Activities">
<li data-bind="activityContent: $data"></li>
</ul>
回答1:
Remove the ko.applyBindings(bindingContext, content);
line in your init
, and remember that update
runs once on init, and then on each update.
Also, you have a larger problem. In the fiddle given above by @nemesv, by not removing the ko.applyBindings()
from the custom binding, the list isn't even iterated the full 5 times.
A DIFFERENT APPROACH
Unless you have great plans for the activityContent
binding beyond this example, you could dispense with the custom binding and simply register a delegate event on your <li>
element in your viewModel. You could then use Knockout's ko.dataFor()
to determine what's been clicked on, and then call NavigatePage(). This approach is far more performant and does not require a custom binding.
You can read about delegate events here.
来源:https://stackoverflow.com/questions/22489262/why-is-this-event-being-handled-twice-in-knockout