Custom Binding - init продолжает вызываться
Я пытался использовать как пользовательский компонент, так и пользовательскую привязку в Knockout для визуализации небольшой визуализации. Я получил это работает, но понял, что решение не было идеальным. Моя пользовательская привязка должна обрабатывать изменения данных с помощью переходов.
Если появится новый предмет, скажем E
Я хотел бы, чтобы он был включен. Мне также нужно обновлять зеленый штрих вокруг каждого круга каждый раз, когда меняется привязка.
Моя проблема в том, что когда мой context
связывание обновлений в приведенном ниже коде, что вся привязка, кажется, переинициализируется. Я думаю, что Knockout под ним удаляет DOM для предыдущего context
и повторно рендерит весь лот - это вызывает рост каждого круга и запускает анимацию нового элемента.
ko.components.register("context", {
// Assume that the view model given to us is already observable, having had a ko.mapping.fromJS() applied or similar
viewModel: function (vm) {
this.context = vm;
},
template: '<div class="card context-card" data-bind="contextViz: context">\
<!-- ko if: context && context.types.length === 0 -->\
<div>Please make a selection to view contextual information here.</div>\
<!-- /ko -->\
</div>\
'
});
Мне интересно, могу ли я что-нибудь сделать, чтобы предотвратить это. По сути хочу старый context
привязка просто обновить, но я не уверен, есть ли способ сделать это.
Я добавил фрагмент кода для иллюстрации. Вот init called
регистрируется каждый раз, когда происходит обновление, я хочу, чтобы это регистрировалось только один раз, и update called
быть зарегистрировано много раз.
var count = 0;
ko.bindingHandlers.contextViz = {
init: function() {
console.log("init called");
},
update: function() {
console.log("update called");
}
};
ko.components.register("context", {
viewModel: function (vm) {
this.context = vm;
},
template: '<div class="card context-card" data-bind="contextViz: context">'
});
var vm = {
context: ko.observable({ count: count })
};
ko.applyBindings(vm);
setInterval(function() {
vm.context({ count: count + 1 });
}, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="component: { name: 'context', params: $root.context }"></div>
1 ответ
Потому что вы напрямую используете свой context
собственность как params
вашего вычисленного нокаутом будет заново визуализировать весь вычисленный, когда context
изменения.
Обычная практика - передавать объект с некоторыми свойствами в качестве params
поэтому при изменении свойств этого объекта компонент не полностью перерисовывается.
Так что вам нужно изменить свой HTMl на:
<div data-bind="component: { name: 'context', params: { context: $root.context }}"></div>
А в вашем вычисленном конструкторе просто напишите:
viewModel: function (params) {
this.context = params.context;
},
var count = 0;
ko.bindingHandlers.contextViz = {
init: function() {
document.getElementById("log").innerHTML += "init called\n";
},
update: function(e,v) {
console.log(ko.unwrap(v())) // make a dependency so it will be called when the bound observable changes
document.getElementById("log").innerHTML += "update called\n";
}
};
ko.components.register("context", {
viewModel: function (params) {
this.context = params.context;
},
template: '<div class="card context-card" data-bind="contextViz: context">'
});
var vm = {
context: ko.observable({ count: count })
};
ko.applyBindings(vm);
setInterval(function() {
vm.context({ count: ++count });
}, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="component: { name: 'context', params: { context: $root.context }}"></div>
<div>log:</div>
<pre id="log"></pre>