JavaScript + jQuery + Angular:找不到元素



我定义了一个JavaScript函数。在这个函数中,我定义了 jQuery 元素类型的变量。因此,变量引用 HTML 上的div。此函数返回具有单个函数 init(( 的对象。

在 $(document(.ready 函数中,我调用 init(( 函数。

问题是当脚本加载时,DOM 还没有准备好,因此引用 jQuery 项的变量被设置为 undefined。

稍后,我在 Angular ngOnInit(( 中调用 init(( 函数以确保事情被很好地初始化,所以什么都没有发生,因为上面的变量是未定义的,并且不会再次重新计算它们。

似乎,当 JavaScript 中的函数被定义时,它的主体会运行,因此变量被运行并设置为 undefined,因为 HTML 元素还没有在 DOM 中。

如何在 init(( 运行时重新计算变量?我无法理解这件事。

谢谢

var mQuickSidebar = function() {
var topbarAside = $('#m_quick_sidebar');
console.log('Function: ', Date.now());
var topbarAsideTabs = $('#m_quick_sidebar_tabs');    
var topbarAsideClose = $('#m_quick_sidebar_close');
var topbarAsideToggle = $('#m_quick_sidebar_toggle');
var topbarAsideContent = topbarAside.find('.m-quick-sidebar__content');
var initMessages = function() {
    var messenger = $('#m_quick_sidebar_tabs_messenger');  
    if (messenger.length === 0) {
        return;
    }
    var messengerMessages = messenger.find('.m-messenger__messages');
    var init = function() {
        var height = topbarAside.outerHeight(true) - 
            topbarAsideTabs.outerHeight(true) - 
            messenger.find('.m-messenger__form').outerHeight(true) - 120;
        // init messages scrollable content
        messengerMessages.css('height', height);
        mApp.initScroller(messengerMessages, {});
    }
    init();        
    // reinit on window resize
    mUtil.addResizeHandler(init);
}
var initSettings = function() { 
    var settings = $('#m_quick_sidebar_tabs_settings');
    if (settings.length === 0) {
        return;
    }
    // init dropdown tabbable content
    var init = function() {
        var height = mUtil.getViewPort().height - topbarAsideTabs.outerHeight(true) - 60;
        // init settings scrollable content
        settings.css('height', height);
        mApp.initScroller(settings, {});
    }
    init();
    // reinit on window resize
    mUtil.addResizeHandler(init);
}
var initLogs = function() {
    // init dropdown tabbable content
    var logs = $('#m_quick_sidebar_tabs_logs');
    if (logs.length === 0) {
        return;
    }
    var init = function() {
        var height = mUtil.getViewPort().height - topbarAsideTabs.outerHeight(true) - 60;
        // init settings scrollable content
        logs.css('height', height);
        mApp.initScroller(logs, {});
    }
    init();
    // reinit on window resize
    mUtil.addResizeHandler(init);
}
var initOffcanvasTabs = function() {
    initMessages();
    initSettings();
    initLogs();
}
var initOffcanvas = function() {
    topbarAside.mOffcanvas({
        class: 'm-quick-sidebar',
        overlay: true,  
        close: topbarAsideClose,
        toggle: topbarAsideToggle
    });   
    // run once on first time dropdown shown
    topbarAside.mOffcanvas().one('afterShow', function() {
        mApp.block(topbarAside);
        setTimeout(function() {
            mApp.unblock(topbarAside);
            topbarAsideContent.removeClass('m--hide');
            initOffcanvasTabs();
        }, 1000);                         
    });
}
return {     
    init: function() { 
        console.log('Inside Init(): ', Date.now());
        console.log($('#m_quick_sidebar')); // topbarAside is undefined here!
        if (topbarAside.length === 0) {
            return;
        }
        initOffcanvas(); 
    }
}; }();
$(document).ready(function() {
    console.log('document.ready: ', Date.now());
    mQuickSidebar.init();
});

问题是你立即调用你的函数mQuickSidebar而不是

看起来,当JavaScript中的函数被定义时,它的身体会运行

var mQuickSidebar = function() {
    var topbarAside = $('#m_quick_sidebar');
    console.log('Function: ', Date.now());
    var topbarAsideTabs = $('#m_quick_sidebar_tabs');    
    var topbarAsideClose = $('#m_quick_sidebar_close');
    var topbarAsideToggle = $('#m_quick_sidebar_toggle');
    var topbarAsideContent = topbarAside.find('.m-quick-sidebar__content');
...
}(); // <---- this runs the function immediately

所以这些 var 声明是运行的,由于 DOM 还没有准备好,这些选择器找不到任何东西。我真的很惊讶它没有抛出某种 $ 未定义的错误

这看起来像模块模式的损坏实现

我在模块模式中重写了您的代码。变化很小。请记住,在 IIFE 内部声明为 var 的所有内容都是私有的,无法通过 mQuickSidebar 访问。只有mQuickSidebarinit功能是公开的。我不知道你需要什么是公共的或私人的。如果您需要进一步澄清,请询问。

作为模块

var mQuickSidebar = (function(mUtil, mApp, $) {
    console.log('Function: ', Date.now());
    var topbarAside;
    var topbarAsideTabs;
    var topbarAsideClose;
    var topbarAsideToggle;
    var topbarAsideContent;
    var initMessages = function() {
        var messenger = $('#m_quick_sidebar_tabs_messenger');  
        if (messenger.length === 0) {
            return;
        }
        var messengerMessages = messenger.find('.m-messenger__messages');
        var init = function() {
            var height = topbarAside.outerHeight(true) - 
                topbarAsideTabs.outerHeight(true) - 
                messenger.find('.m-messenger__form').outerHeight(true) - 120;
            // init messages scrollable content
            messengerMessages.css('height', height);
            mApp.initScroller(messengerMessages, {});
        };
        init();        
        // reinit on window resize
        mUtil.addResizeHandler(init);
    };
    var initSettings = function() { 
        var settings = $('#m_quick_sidebar_tabs_settings');
        if (settings.length === 0) {
            return;
        }
        // init dropdown tabbable content
        var init = function() {
            var height = mUtil.getViewPort().height - topbarAsideTabs.outerHeight(true) - 60;
            // init settings scrollable content
            settings.css('height', height);
            mApp.initScroller(settings, {});
        };
        init();
        // reinit on window resize
        mUtil.addResizeHandler(init);
    };
    var initLogs = function() {
        // init dropdown tabbable content
        var logs = $('#m_quick_sidebar_tabs_logs');
        if (logs.length === 0) {
            return;
        }
        var init = function() {
            var height = mUtil.getViewPort().height - topbarAsideTabs.outerHeight(true) - 60;
            // init settings scrollable content
            logs.css('height', height);
            mApp.initScroller(logs, {});
        };
        init();
        // reinit on window resize
        mUtil.addResizeHandler(init);
    };
    var initOffcanvasTabs = function() {
        initMessages();
        initSettings();
        initLogs();
    };
    var initOffcanvas = function() {
        topbarAside.mOffcanvas({
            class: 'm-quick-sidebar',
            overlay: true,  
            close: topbarAsideClose,
            toggle: topbarAsideToggle
        });   
        // run once on first time dropdown shown
        topbarAside.mOffcanvas().one('afterShow', function() {
            mApp.block(topbarAside);
            setTimeout(function() {
                mApp.unblock(topbarAside);
                topbarAsideContent.removeClass('m--hide');
                initOffcanvasTabs();
            }, 1000);                         
        });
    };
    return {     
        init: function() { 
            console.log('Inside Init(): ', Date.now());
            console.log($('#m_quick_sidebar')); // topbarAside is undefined here!
            topbarAside = $('#m_quick_sidebar');
            topbarAsideTabs = $('#m_quick_sidebar_tabs');    
            topbarAsideClose = $('#m_quick_sidebar_close');
            topbarAsideToggle = $('#m_quick_sidebar_toggle');
            topbarAsideContent = topbarAside.find('.m-quick-sidebar__content');
            if (topbarAside.length === 0) {
                return;
            }
            initOffcanvas(); 
        }
    }; 
})(mUtil, mApp, $);
$(document).ready(function() {
    console.log('document.ready: ', Date.now());
    mQuickSidebar.init();
});

最新更新