mutationobserver 在没有更改和方法未找到问题时触发

mutationobserver firing when no change and method not found issue

我使用 MutationObserver 在元素上放置了一个观察者。在一个用例中,它完全按预期工作并在更改后触发,但在元素未更改的另一个用户操作中它似乎正在触发 - 但在这样做时它会出现一个方法未找到错误,它不会出现在使用同一个观察者的第一个用例中。

观察者观察元素内的更新,当用户选择图像时,该元素会更新图像。

在工作案例中,用户从图像列表中选择一个图像,然后更新并且观察者触发 - 一切都很好。 在非工作情况下,用户上传图像 - 此时虽然目标元素没有发生更新(在视图中但在颜色框下方。(不确定是否相关)。

触发本身通常不会成为问题,但在观察者回调中它调用了一个方法,在第二种情况下它表示未定义。 所以在第一个实例中没有错误,但在第二个实例中:

我收到一个错误 _this.buttons is not a function at MutationObserver.callback

正在使用 webpack 编译代码

  1. 1.为什么观察者在没有出现正在观察的变化类型时触发
  2. 为什么在这种情况下会出现此错误 - 当方法似乎存在并且在有更改时按预期工作时?

感谢任何帮助

这是代码 - 这个 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这个`