mutationobserver 在没有更改和方法未找到问题时触发
mutationobserver firing when no change and method not found issue
我使用 MutationObserver
在元素上放置了一个观察者。在一个用例中,它完全按预期工作并在更改后触发,但在元素未更改的另一个用户操作中它似乎正在触发 - 但在这样做时它会出现一个方法未找到错误,它不会出现在使用同一个观察者的第一个用例中。
观察者观察元素内的更新,当用户选择图像时,该元素会更新图像。
在工作案例中,用户从图像列表中选择一个图像,然后更新并且观察者触发 - 一切都很好。
在非工作情况下,用户上传图像 - 此时虽然目标元素没有发生更新(在视图中但在颜色框下方。(不确定是否相关)。
触发本身通常不会成为问题,但在观察者回调中它调用了一个方法,在第二种情况下它表示未定义。
所以在第一个实例中没有错误,但在第二个实例中:
我收到一个错误 _this.buttons is not a function at MutationObserver.callback
正在使用 webpack 编译代码
- 1.为什么观察者在没有出现正在观察的变化类型时触发?
- 为什么在这种情况下会出现此错误 - 当方法似乎存在并且在有更改时按预期工作时?
感谢任何帮助
这是代码 - 这个 class 管理页面的操作 - 我删除了一些代码以尽量保持简洁(但仍然有点冗长 - 重构待完成):
首先是观察者的代码:
const callback = (mutationsList, observer) =>{
// Use traditional 'for loops' for IE 11
for(let mutation of mutationsList) {
if (mutation.type === 'childList') {
console.log('A child node has been added or removed.');
module.buttons();
module.initialiseControls();
}
else if (mutation.type === 'attributes') {
console.log('The ' + mutation.attributeName + ' attribute was modified.');
}
}
};
这里是包含观察者方法的class
export let fileImageWidgetControls = class {
constructor({
previewBtn = '.preview-image',
addBtn = '#add-image',
replaceBtn = '#replace-image',
removeBtn = '#remove-image'
} = {}) {
this.options = {
previewBtn: previewBtn,
addBtn: addBtn,
replaceBtn: replaceBtn,
removeBtn: removeBtn
}
this.filemanager = new filemanagerHandler; //file selector class
this.imageWidget = new updateWidget; //handles updating the image
this.initialiseControls(); //sets up the page controls
this.observer(); //sets up the observer
}
openFileManager = () =>{
//open colbox (which opens filemanager page
//When filemanager loaded then initialise filemanager
$(document).bind('cbox_complete', ()=>{
console.log('Colbox complete');
this.filemanager.init();
});
//handle colbox closing and update image in widget (if needed)
$(document).bind('cbox_closed', ()=>{
let selectedAsset = this.filemanager.getSelectedAsset();
if(selectedAsset) {
this.imageWidget.update(selectedAsset.filename);
}
});
colBox.init({
href: this.options.serverURL
});
colBox.colorbox()
}
remove = ()=> {
//clear file and update visible buttons
this.buttons();
}
/**
* preview the image in a colorbox
* @param filename
*/
preview = function () {
//open image in preview
}
/**
* select image via filemanager
*/
select = () =>{
console.log('select');
this.openFileManager();
}
replace = () => {
// image already exists in widget but needs replacing
console.log('replace');
this.openFileManager();
}
initialiseControls = () => {
console.log('init controls');
//preview button
$(this.options.previewBtn).on('click', (e) => {
e.preventDefault();
this.preview();
}).attr('disabled', false);
$('#img-preview-link').on('click', (e)=> {
e.preventDefault();
this.preview();
});
// add button
$(this.options.addBtn).on('click', (e) => {
e.preventDefault();
this.select();
}).attr('disabled', false);
//replace button
$(this.options.replaceBtn).on('click', (e) => {
e.preventDefault();
this.replace();
}).attr('disabled', false);
//remove button
$(this.options.removeBtn).on('click', (e) => {
e.preventDefault();
this.remove();
}).attr('disabled', false);
this.buttons();
}
//set an observer to watch preview image for changes
observer= ()=> {
const module = this;
const targetNode = document.getElementById('image-preview-panel');
const config = { attributes: true, childList: true, subtree: true };
const callback = (mutationsList, observer) =>{
// Use traditional 'for loops' for IE 11
for(let mutation of mutationsList) {
if (mutation.type === 'childList') {
console.log('A child node has been added or removed.');
module.buttons();
module.initialiseControls();
}
else if (mutation.type === 'attributes') {
console.log('The ' + mutation.attributeName + ' attribute was modified.');
}
}
};
const observer = new MutationObserver(callback);
observer.observe(targetNode, config);
}
buttons = function() {
let imagePreview = $('#image-preview');
if(imagePreview.data('updated')=== true && imagePreview.data('updated') !== "false") {
console.log('image present');
$(this.options.addBtn).fadeOut().attr('disabled', true);
$(this.options.removeBtn).fadeIn().attr('disabled', false);
$(this.options.replaceBtn).fadeIn().attr('disabled', false);
$(this.options.previewBtn).fadeIn().attr('disabled', false);
} else {
console.log('image not present', imagePreview.data());
console.log('image element:', imagePreview);
$(this.options.addBtn).fadeIn().attr('disabled', false);
$(this.options.removeBtn).fadeOut().attr('disabled', true);
$(this.options.replaceBtn).fadeOut().attr('disabled', true);
$(this.options.previewBtn).fadeOut().attr('disabled', true);
}
}
}
我从教程中复制了代码,因此在我重构之前有一些评论
添加了const module = this; within the method and referenced that within the nested function and now pointing to the correct
这个`
我使用 MutationObserver
在元素上放置了一个观察者。在一个用例中,它完全按预期工作并在更改后触发,但在元素未更改的另一个用户操作中它似乎正在触发 - 但在这样做时它会出现一个方法未找到错误,它不会出现在使用同一个观察者的第一个用例中。
观察者观察元素内的更新,当用户选择图像时,该元素会更新图像。
在工作案例中,用户从图像列表中选择一个图像,然后更新并且观察者触发 - 一切都很好。 在非工作情况下,用户上传图像 - 此时虽然目标元素没有发生更新(在视图中但在颜色框下方。(不确定是否相关)。
触发本身通常不会成为问题,但在观察者回调中它调用了一个方法,在第二种情况下它表示未定义。 所以在第一个实例中没有错误,但在第二个实例中:
我收到一个错误 _this.buttons is not a function at MutationObserver.callback
正在使用 webpack 编译代码
- 1.为什么观察者在没有出现正在观察的变化类型时触发?
- 为什么在这种情况下会出现此错误 - 当方法似乎存在并且在有更改时按预期工作时?
感谢任何帮助
这是代码 - 这个 class 管理页面的操作 - 我删除了一些代码以尽量保持简洁(但仍然有点冗长 - 重构待完成):
首先是观察者的代码:
const callback = (mutationsList, observer) =>{
// Use traditional 'for loops' for IE 11
for(let mutation of mutationsList) {
if (mutation.type === 'childList') {
console.log('A child node has been added or removed.');
module.buttons();
module.initialiseControls();
}
else if (mutation.type === 'attributes') {
console.log('The ' + mutation.attributeName + ' attribute was modified.');
}
}
};
这里是包含观察者方法的class
export let fileImageWidgetControls = class {
constructor({
previewBtn = '.preview-image',
addBtn = '#add-image',
replaceBtn = '#replace-image',
removeBtn = '#remove-image'
} = {}) {
this.options = {
previewBtn: previewBtn,
addBtn: addBtn,
replaceBtn: replaceBtn,
removeBtn: removeBtn
}
this.filemanager = new filemanagerHandler; //file selector class
this.imageWidget = new updateWidget; //handles updating the image
this.initialiseControls(); //sets up the page controls
this.observer(); //sets up the observer
}
openFileManager = () =>{
//open colbox (which opens filemanager page
//When filemanager loaded then initialise filemanager
$(document).bind('cbox_complete', ()=>{
console.log('Colbox complete');
this.filemanager.init();
});
//handle colbox closing and update image in widget (if needed)
$(document).bind('cbox_closed', ()=>{
let selectedAsset = this.filemanager.getSelectedAsset();
if(selectedAsset) {
this.imageWidget.update(selectedAsset.filename);
}
});
colBox.init({
href: this.options.serverURL
});
colBox.colorbox()
}
remove = ()=> {
//clear file and update visible buttons
this.buttons();
}
/**
* preview the image in a colorbox
* @param filename
*/
preview = function () {
//open image in preview
}
/**
* select image via filemanager
*/
select = () =>{
console.log('select');
this.openFileManager();
}
replace = () => {
// image already exists in widget but needs replacing
console.log('replace');
this.openFileManager();
}
initialiseControls = () => {
console.log('init controls');
//preview button
$(this.options.previewBtn).on('click', (e) => {
e.preventDefault();
this.preview();
}).attr('disabled', false);
$('#img-preview-link').on('click', (e)=> {
e.preventDefault();
this.preview();
});
// add button
$(this.options.addBtn).on('click', (e) => {
e.preventDefault();
this.select();
}).attr('disabled', false);
//replace button
$(this.options.replaceBtn).on('click', (e) => {
e.preventDefault();
this.replace();
}).attr('disabled', false);
//remove button
$(this.options.removeBtn).on('click', (e) => {
e.preventDefault();
this.remove();
}).attr('disabled', false);
this.buttons();
}
//set an observer to watch preview image for changes
observer= ()=> {
const module = this;
const targetNode = document.getElementById('image-preview-panel');
const config = { attributes: true, childList: true, subtree: true };
const callback = (mutationsList, observer) =>{
// Use traditional 'for loops' for IE 11
for(let mutation of mutationsList) {
if (mutation.type === 'childList') {
console.log('A child node has been added or removed.');
module.buttons();
module.initialiseControls();
}
else if (mutation.type === 'attributes') {
console.log('The ' + mutation.attributeName + ' attribute was modified.');
}
}
};
const observer = new MutationObserver(callback);
observer.observe(targetNode, config);
}
buttons = function() {
let imagePreview = $('#image-preview');
if(imagePreview.data('updated')=== true && imagePreview.data('updated') !== "false") {
console.log('image present');
$(this.options.addBtn).fadeOut().attr('disabled', true);
$(this.options.removeBtn).fadeIn().attr('disabled', false);
$(this.options.replaceBtn).fadeIn().attr('disabled', false);
$(this.options.previewBtn).fadeIn().attr('disabled', false);
} else {
console.log('image not present', imagePreview.data());
console.log('image element:', imagePreview);
$(this.options.addBtn).fadeIn().attr('disabled', false);
$(this.options.removeBtn).fadeOut().attr('disabled', true);
$(this.options.replaceBtn).fadeOut().attr('disabled', true);
$(this.options.previewBtn).fadeOut().attr('disabled', true);
}
}
}
我从教程中复制了代码,因此在我重构之前有一些评论
添加了const module = this; within the method and referenced that within the nested function and now pointing to the correct
这个`