我有一个与Scribe接口的自定义绑定,这是一个令人满意的WYSIWYG编辑器。它在编辑器内容更改时更新关联的observable,并在关联的observable执行时更新编辑器:
ko.bindingHandlers.editor = {
init: function(element, valueAccessor) {
var $element = $(element),
content = ko.unwrap(valueAccessor()),
scribe;
// create a new editor instance
scribe = new Scribe(element);
// store it for later access in our 'update' handler
$element.data('scribe', scribe);
// set the initial editor content
scribe.setContent(content);
// update the observable whenever the editor changes
scribe.on('content-changed', function() {
var observable = valueAccessor(),
content = scribe.getHTML();
observable(content);
});
},
update: function(element, valueAccessor) {
var $element = $(element),
content = ko.unwrap(valueAccessor());
// update the editor content when the observable changes
$element.data('scribe').setContent(content);
}
};
问题在于:
通常这不是什么大问题,只是没必要。但就我而言,editor.setContent
的副作用是将光标位置重置为输入的开头 - everything you enter is reversed。
我需要更新编辑器,如果 - 且仅当 - 在应用程序的其他位置更改了observable。我正在寻找的是一种避免使用源自编辑器本身的更改来更新编辑器的方法。
我怎样才能最好地避免这些循环更新?
更新 我发现了一种避免直接问题的明显方法 - 在更新处理程序中,只需在进行更新之前将可观察内容与当前编辑器内容进行比较:
if ($element.data('scribe').getHTML() !== content) {
$element.data('scribe').setContent(content);
}
如果只是为了避免不必要的更新调用,我仍然会对一般答案感兴趣。
答案 0 :(得分:1)
基于RPNiemeyers recommendation,我移动了observable - >组件更新功能来自绑定' update
处理程序init
处理程序:
ko.bindingHandlers.editor = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var $element = $(element),
content = ko.unwrap(valueAccessor()),
ignoreObservableChanges = false,
scribe;
scribe = new Scribe(element);
$element.data('scribe', scribe);
scribe.setContent(content);
scribe.on('content-changed', function() {
var observable = valueAccessor(),
content = scribe.getHTML();
ignoreObservableChanges = true;
observable(content);
ignoreObservableChanges = false;
});
valueAccessor().subscribe(function(newValue) {
if (ignoreObservableChanges) {
return;
}
scribe.setContent(newValue);
});
}
};
组件 - >可观察的更新者和可观察的 - >组件更新程序现在在其范围内共享ignoreObservableChanges
标志,因此前者可以指示后者何时跳过更新。