防止敲除将绑定应用到不可见的元素
Prevent knockout from applying bindings to elements that are not visible
我正在渲染一个大型递归数据结构,并试图让用户能够在该结构内切换对单个元素的编辑。由于编辑器绑定应用于所有元素,即使它们尚不可见,我在应用绑定时遇到性能问题。
<div data-bind="visible: isEditable()">
<textarea data-bind="kendoEditor: { value: name }" > </textarea>
<button type="button" data-bind="click: toggleEdit(false)">Update</button>
</div>
如果您查看以下示例,它似乎可以正常工作。您可以单击一个元素,它会启用一个编辑器,您可以单击更新并应用更改。
但是,如果您查看以下我添加了更多数据的示例,由于将 kendoEditing 绑定应用于列表中的所有元素,初始加载速度非常慢。
有什么方法可以防止绑定应用于尚不可见的元素?
您提前进行了大量切换,因为您的点击绑定应该获得一个功能,而不是一段代码。这是一个常见的错误。
为了避免绑定一百万个编辑器,您可以只交换模板,而不是有可见和不可见的元素:
<ul data-bind="template: { name: 'itemTmpl', foreach: Items }"></ul>
<script id="itemTmpl" type="text/html">
<li>
<div data-bind="template: isEditable() ? 'editable' : 'notEditable'"></div>
<ul data-bind="template: { name: 'itemTmpl', foreach: $data.items }"></ul>
</li>
</script>
<script id="notEditable" type="text/html">
<span data-bind="html: name, click: toggleEdit.bind(null,true)">
</span>
</script>
<script id="editable" type="text/html">
<textarea data-bind="kendoEditor: { value: name }"></textarea>
<button type="button" data-bind="click: toggleEdit.bind(null, false)">Update</button>
</script>
Roy 的回答可能更好,但是,是的,有一种方法可以防止绑定应用于后代元素。为此,您需要使用 init
的自定义绑定,其中 returns:
return { controlsDescendantBindings: true };
您以后可以使用
ko.applyBindingsToDescendants(bindingContext, element)
应用绑定。
例如像这样:
ko.bindingHandlers.myVisible = {
init: function(element, valueAccessor) {
var visible = ko.unwrap(valueAccessor());
if (visible) {
$(element).show();
$(element).data('bindingsApplied', true);
} else {
$(element).hide();
$(element).data('bindingsApplied', false);
return { controlsDescendantBindings: true };
}
},
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var visible = ko.unwrap(valueAccessor());
if (visible) {
if (!$(element).data('bindingsApplied')) {
ko.applyBindingsToDescendants(bindingContext, element);
$(element).data('bindingsApplied', true);
}
$(element).show();
} else {
$(element).hide();
}
}
}
我正在渲染一个大型递归数据结构,并试图让用户能够在该结构内切换对单个元素的编辑。由于编辑器绑定应用于所有元素,即使它们尚不可见,我在应用绑定时遇到性能问题。
<div data-bind="visible: isEditable()">
<textarea data-bind="kendoEditor: { value: name }" > </textarea>
<button type="button" data-bind="click: toggleEdit(false)">Update</button>
</div>
如果您查看以下示例,它似乎可以正常工作。您可以单击一个元素,它会启用一个编辑器,您可以单击更新并应用更改。
但是,如果您查看以下我添加了更多数据的示例,由于将 kendoEditing 绑定应用于列表中的所有元素,初始加载速度非常慢。
有什么方法可以防止绑定应用于尚不可见的元素?
您提前进行了大量切换,因为您的点击绑定应该获得一个功能,而不是一段代码。这是一个常见的错误。
为了避免绑定一百万个编辑器,您可以只交换模板,而不是有可见和不可见的元素:
<ul data-bind="template: { name: 'itemTmpl', foreach: Items }"></ul>
<script id="itemTmpl" type="text/html">
<li>
<div data-bind="template: isEditable() ? 'editable' : 'notEditable'"></div>
<ul data-bind="template: { name: 'itemTmpl', foreach: $data.items }"></ul>
</li>
</script>
<script id="notEditable" type="text/html">
<span data-bind="html: name, click: toggleEdit.bind(null,true)">
</span>
</script>
<script id="editable" type="text/html">
<textarea data-bind="kendoEditor: { value: name }"></textarea>
<button type="button" data-bind="click: toggleEdit.bind(null, false)">Update</button>
</script>
Roy 的回答可能更好,但是,是的,有一种方法可以防止绑定应用于后代元素。为此,您需要使用 init
的自定义绑定,其中 returns:
return { controlsDescendantBindings: true };
您以后可以使用
ko.applyBindingsToDescendants(bindingContext, element)
应用绑定。
例如像这样:
ko.bindingHandlers.myVisible = {
init: function(element, valueAccessor) {
var visible = ko.unwrap(valueAccessor());
if (visible) {
$(element).show();
$(element).data('bindingsApplied', true);
} else {
$(element).hide();
$(element).data('bindingsApplied', false);
return { controlsDescendantBindings: true };
}
},
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var visible = ko.unwrap(valueAccessor());
if (visible) {
if (!$(element).data('bindingsApplied')) {
ko.applyBindingsToDescendants(bindingContext, element);
$(element).data('bindingsApplied', true);
}
$(element).show();
} else {
$(element).hide();
}
}
}