jQuery组织document.ready逻辑

时间:2012-12-04 05:08:19

标签: jquery document-ready

我所使用的大多数支持jQuery的Web应用程序都以两种方式之一组织了document.ready逻辑。

  1. 全局document.ready用于站点范围的JS文件,所有document.ready逻辑都包含在该执行块中。
  2. document.ready logic显式添加到需要它们的特定页面。
  3. 通常情况下,我使用选项1,以便javascript将享受javascript整合和缩小的好处,可以轻松应用于独立文件与页面上的javascript块。

    但是,随着网站的增长,需要在document.ready执行的逻辑数量也会增加,我怀疑被评估的选择器数量会影响网站的快速性。

    我考虑过开发一个框架,可以应用一种全局技术,使用URL或根元素属性来确定应该在document.ready上执行哪些代码,并减少选择器的数量被评估。

    编辑:更多澄清...... 在一个简单的例子中,我有2个不同的页面。在每个页面上,逻辑(包括选择器)需要在document.ready上执行,但理想情况下,逻辑只在加载这些页面时执行,而不是在整个站点的每个页面上执行。

    这样的事情是否已经存在,或者一般来说选择器足够便宜,我不应该关心?

5 个答案:

答案 0 :(得分:0)

我一直在使用你在我最新项目中描述的东西。我在每个页面中给出了HTML标记一个唯一的ID,然后我用它来初始化特定于该页面的代码:

$(function() {
    //for index.html (view/edit)
    if($("html#view").length>0){
        ReadView();
    }
    //for create.html (add)
    if($("html#create").length>0){
        CreateView();
    }
    globalFunction();
});

var ReadView = function(){
    ...
};

var CreateView = function(){
    ...
};

var globalFunction = function(){
    ...
};

这不仅有助于保持JavaScript“快速”,就像你说的那样,但它有助于名称间距并有助于防止可变冲突。我还发现,当其他程序员查看代码,以更有条理的方式理解事物时,它会有所帮助。

答案 1 :(得分:0)

第一关,我主要使用单页应用程序。

这就是我经常操作的方式:

// Main module
;(function($, win, undefined) {
    var module = {
        _currentPanel,
        initialize: function() {
            // all my global bindings here
        },

        // Only included to understand whats going on in the sub-module below
        displayPanel: function(panelName) {
            if (!!module._currentPanel) {
                $(module._currentPanel)
                    .hide(0)
                    .triggerHandler('hide.panel');
            }

            module._currentPanel = panelName;

            $(panelName)
                .show(0)
                .triggerHandler('show.panel');
        },          
    };

    $.extend("namespace", module);
})(jQuery, window);



// Sub modules
;(function($, win, undefined) {
    var module = {
        something: function() {
            // ..nothing to see here, this is just how i construct my modules
        }
    };


    // Event bindings specific to this module
    $('#geo-panel').bind('show.panel', function() {
        // wire up init() stuff   
    });
    $('#geo-panel').bind('hide.panel', function() {
        // wire up dispose() stuff
    }); 

    $.extend("namespace", module);
})(jQuery, window);

那么最近怎么样?

我的主要模块包含所有全局内容..这是合乎逻辑的:)使用initialize()函数,当我加载页面时,我调用某处。这将挂钩我在所有页面(或本例中的视图)上有用的通用绑定/选择器。

然后我的子模块将绑定到我在应用程序中显示各种伪页面时触发的事件。他们都对.triggerHandler()作出反应,我使用它可以在整个网站中分离我的逻辑。

displayPanel( “#地理面板”);

displayPanel( “#一些其它面板”);

主要模块和然后将子模块聚合成一个大的js文件。这里有一些冗余的$ .extend()(我用它来动态创建命名空间),它允许我将所有内容拆分为自动构建的专用子模块(首选项,配置文件,搜索...)在应用程序构建上汇总。

但是,如果我没有使用单页应用程序,那么我会:

  1. 只需将#panel-geo中的所有引用更改为更像#pageX #panel-geo
  2. 的内容
  3. 或者为所有页面选择1个常用js,为每个页面设置1个特定js

答案 2 :(得分:0)

我所做的是拥有两组(可能更多)文件。一个app.js文件,其中包含对站点是全局的内容,以及每个页面的page.js文件,其中包含特定于该页面的内容。

page.js文件设置了一个对象myapp.page对象,该对象包含特定于该页面的函数,但与具有全局上下文的事物相关。此文件还包含特定于该页面的内容,与全局内容相关。

典型的page.js看起来像这样:

var myapp = mayapp || {};
myapp.page = {
    onReady: function($, undefined) {
        // page specific initialization that will need to use
        // things initialized in the global initialization
    },

    // for other events that I want some page-specific behavior 
    // in addition to the global behavior. For example, onresize:
    onResize: function(e, anything) {
        // page specific response to some event
        // that uses or relies on things done in the global
        // onresize listener
    }
}

// stuff that is page specific that is completely autonomous.
// This could also be included in the myapp.page.onReady, if preferred.
// I like the seperation because it illustrates what on the page 
// depends on global resources.
$().ready(function() {
    $('#some-form').submit(function(e) {
        // the form only exists on this page so no need to put it in
        // the page.onReady callback function
    });
});

app.js文件使用$()。ready(...)在页面加载时执行操作。然后它调用页面特定的JS:

$().ready(function() {

    var myapp = mayapp || {};

    // do global stuff first
    globalStuff();
    // then page specific
    if (myapp.page && typeof myapp.page.onReady === 'function') {
        myapp.page.onReady($);
    }

    // if there are some events that have both global page specific things
    // going on I would have something like this:
    window.addEventListener('resize', function(e) {
        // global behavior
        someResult = processedTheSameOnAllPges();

        // then page specific
        if (myapp.page && typeof myapp.page.onResize === 'function') {
            myapp.page.onResize(e, someResult);
        }
    });
})

我将这些事情分开,主要是为了简化,但肯定会对大型网站产生性能影响。这确实是单独文件的缺点,因此将有两次下载。但是,每个页面只是下载并执行它所需的内容。

关于性能,如果由于您的选择器而导致初始化缓慢,可以考虑将其部分或全部用于原生。

对于特定数据,特别关注选择器(在OP中多次提到),我能提供的最好的是一些有趣的jsPerf案例:

这些测试的一个巨大限制,恕我直言,是他们使用的'准备代码'。这些测试场景是不现实的,从我注意到的情况来看,运行选择器的DOM对其性能有很大的影响。

答案 3 :(得分:0)

组织你页面的替代方法可以是用户jquery的triggerHandler来“拆分” document.ready 事件,如下所示:

准备就绪:

$(namespace.eventPool).triggerHandler("namespace.preready");
$(namespace.eventPool).triggerHandler("namespace.domready");
$(namespace.eventPool).triggerHandler("namespace.postready");

来自ajax(示例)的加载模板:

$(namespace.eventPool).triggerHandler("namespace.templates.loaded");

伪代码中的示例用法:

function loadTemplates(){
    $.get...
    $(namespace.eventPool).triggerHandler("namespace.templates.loaded");
}

$(namespace.eventPool).on({
   "namespace.preready":loadTemplates,
   "namespace.templates.loaded":invalidateCache
});

这个想法是为了避免一下子把所有东西都关掉,而且只有一小部分基于事件的pub / sub

答案 4 :(得分:-1)

每个页面“知道”需要在该页面上执行哪个JS。因此,在.js文件中定义这些函数,并在HTML标记中调用doc-ready以仅调用这些函数。

虽然你应该避免在你的HTML中放置重要的JS代码,但是调用一两个init函数是完全可以接受的。