自定义绑定 - init 不断被调用
Custom Binding - init keeps getting called
我一直在尝试使用自定义组件,然后使用 Knockout 中的自定义绑定来呈现小型可视化。我得到了这个工作,但意识到解决方案并不理想。我的自定义绑定应该通过使用转换来处理对数据的更改。
如果出现新项目,比如 E
,我希望它过渡进来。我还需要在每次绑定更改时更新每个圆圈周围的绿色描边。
我的问题是,当我的 context
绑定在下面的代码中更新时,整个绑定似乎重新初始化。我认为下面的 Knockout 正在删除之前 context
的 DOM 并重新渲染整个地块 - 这会导致每个圆圈变大并触发新项目动画。
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>
因为你直接使用你的 context
属性 作为你计算的 KO 的 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>
我一直在尝试使用自定义组件,然后使用 Knockout 中的自定义绑定来呈现小型可视化。我得到了这个工作,但意识到解决方案并不理想。我的自定义绑定应该通过使用转换来处理对数据的更改。
如果出现新项目,比如 E
,我希望它过渡进来。我还需要在每次绑定更改时更新每个圆圈周围的绿色描边。
我的问题是,当我的 context
绑定在下面的代码中更新时,整个绑定似乎重新初始化。我认为下面的 Knockout 正在删除之前 context
的 DOM 并重新渲染整个地块 - 这会导致每个圆圈变大并触发新项目动画。
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>
因为你直接使用你的 context
属性 作为你计算的 KO 的 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>