我正在展示一个巨大的表格结构与淘汰赛。用户可以通过单击行上的复选框来删除行:
data-bind="checked: row.removed"
问题是该表必须在点击时重新呈现,在慢速计算机/浏览器上需要一到两秒钟 - 复选框在表格呈现后更改其状态,因此UI感觉无响应。 我想创建一个包装函数,它执行与默认检查绑定相同的操作,但另外显示一个加载器符号 - 然后在检查的绑定完成其工作后再次隐藏它。类似的东西:
ko.bindingHandlers.checkedWithLoader = {
update: function(element, valueAccessor, allBindings) {
loader.show();
// call knockout's default checked binding here
loader.hide();
}
};
这样的事情可能吗?还有更好的选择吗?
答案 0 :(得分:7)
您可以使用ko.applyBindingsToNode
:
ko.applyBindingsToNode(element, { checked: valueAccessor() })
Knockout的源主动公开此方法(here)并在其自己的文档页面(here)的示例中引用它。
虽然处理缓慢渲染但它可能无法解决您的问题......
您还可以在viewmodel中创建一个额外的图层,以构建加载功能:
this.checked = ko.observable(false);
this.isLoading = ko.observable(false);
this.showLargeAndSlowTable = ko.observable(false);
this.checked.subscribe(function(isChecked) {
this.isLoading(true);
this.showLargeAndSlowTable(isChecked);
this.isLoading(false);
}, this);
您需要绑定到if
的{{1}}或with
绑定,并将复选框值绑定到showLargeAndSlowTable
。
在某些情况下,您可能需要在设置checked
observable和注入大数据集之间强制重新绘制。否则,淘汰赛和浏览器可以将这些更新捆绑到一个框架中。
您可以将loading
和showLargeAndSlowTable
放在isLoading(false)
中,或者使用延迟/限制的其他可观察项来触发setTimeout
之后的工作&# 39;有时间改变:
isLoading

function AppViewModel() {
var self = this;
// The checkbox value that triggers the slow UI update
this.showLargeTable = ko.observable(false);
// Checkbox change triggers things
this.showLargeTable.subscribe(updateUI)
// Indicates when we're loading:
this.working = ko.observable(false);
this.delayedWorking = ko.pureComputed(function() {
return self.working();
}).extend({ throttle: 10 });
// Instead of directly subscribing to `working`, we
// subscribe to the delayed copy
this.delayedWorking.subscribe(function(needsWork) {
if (needsWork) {
doWork();
self.working(false);
}
});
function updateUI(showTable) {
if (showTable) {
self.working(true); // Triggers a slightly delayed update
} else {
self.data([]);
}
}
// Some data from doc. page to work with
function doWork() {
// (code only serves to mimic a slow render)
for (var i = 0; i < 1499; i++) {
self.data([]);
self.data(data.reverse());
}
};
var data = [
{ name: 'Alfred', position: 'Butler', location: 'London' },
{ name: 'Bruce', position: 'Chairman', location: 'New York' }
];
// Some data to render
this.data = ko.observableArray([]);
}
ko.applyBindings(new AppViewModel());
&#13;
.is-loading {
height: 100px;
background: red;
display: flex;
align-items: center;
justify-content: center;
}
.is-loading::after {
content: "LOADING";
color: white;
}
&#13;