Ответ 1
Как получить доступ к другим связям в пользовательской привязке
Вы можете использовать ko.applyBindingsToNode
:
ko.applyBindingsToNode(element, { checked: valueAccessor() })
Источник нокаута активно раскрывает этот метод (здесь) и ссылается на него в примере на своей странице документации (здесь).
Вероятно, это не решит вашу проблему при обработке медленных рендерингов, хотя...
Обработка медленных обновлений
Вы также можете создать дополнительный слой в своей модели 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
или with
, привязанная к showLargeAndSlowTable
, и привяжите значение флажка к checked
.
В некоторых случаях вам может потребоваться принудительно перерисовать между установкой loading
наблюдаемой и инъекцией большого набора данных. В противном случае нокаут и браузер могут связывать эти обновления с одним фреймом.
Вы можете достичь этого, поместив showLargeAndSlowTable
и isLoading(false)
в setTimeout
, или используя задержанный/дросселируемый дополнительный наблюдаемый, который запускает работу после того, как 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());
.is-loading {
height: 100px;
background: red;
display: flex;
align-items: center;
justify-content: center;
}
.is-loading::after {
content: "LOADING";
color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<label>
<input type="checkbox" data-bind="checked: showLargeTable, disable: working">Show slowly rendered table
</label>
<table data-bind="css: { 'is-loading': working }">
<tbody data-bind="foreach: data">
<tr>
<td data-bind="text: name"></td>
<td data-bind="text: position"></td>
<td data-bind="text: location"></td>
</tr>
</tbody>
</table>
<em>Example based on the <a href="#" onclick="location.href='http://knockoutjs.com/documentation/deferred-updates.html'; return false;">knockout docs</a></em>