javascript:如何在没有 jquery 的情况下编写 $(document).ready 之类的事件

IT技术 javascript domready
2021-02-01 18:58:57

在 jquery $(document).ready(function) 或 $(function) 中,没有 jquery 我怎么能做同样的事情,我需要浏览器兼容,并允许附加多个函数。

注意:dom ready!= window onload

6个回答

这是 jQuery 包装您正在寻找的函数的方式 - 代码段不需要 jQuery,并且是跨浏览器兼容的。我已将所有对 jQuery.ready() 的调用替换为yourcallback- 您需要定义。

这里发生了什么:

  • 首先,DOMContentLoaded定义了函数,它将在 DOMContentLoaded 事件触发时使用——它确保回调只被调用一次。
  • 检查文档是否已经加载 - 如果是,立即触发回调
  • 否则嗅探特征 ( document.addEventListener/ document.attachEvent) 并将回调绑定到它(IE 和普通浏览器不同,加上 onload 回调)

从 jQuery 1.4.3 开始,函数 bindReady() 和 DOMContentLoaded

/*
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*/
// Cleanup functions for the document ready method
// attached in the bindReady handler
if ( document.addEventListener ) {
DOMContentLoaded = function() {
    document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
    //jQuery.ready();
            yourcallback();
};

} else if ( document.attachEvent ) {
DOMContentLoaded = function() {
    // Make sure body exists, at least, in case IE gets a little overzealous 
            if ( document.readyState === "complete" ) {
        document.detachEvent( "onreadystatechange", DOMContentLoaded );
        //jQuery.ready();
                    yourcallback();
    }
    };
}

// Catch cases where $(document).ready() is called after the
// browser event has already occurred.
if ( document.readyState === "complete" ) {
    // Handle it asynchronously to allow scripts the opportunity to delay ready
//return setTimeout( jQuery.ready, 1 );
    // ^^ you may want to call *your* function here, similarly for the other calls to jQuery.ready
    setTimeout( yourcallback, 1 );
}

// Mozilla, Opera and webkit nightlies currently support this event
if ( document.addEventListener ) {
    // Use the handy event callback
document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
// A fallback to window.onload, that will always work
//window.addEventListener( "load", jQuery.ready, false );
    window.addEventListener( "load", yourcallback, false );
 // If IE event model is used
 } else if ( document.attachEvent ) {
        // ensure firing before onload,
        // maybe late but safe also for iframes
        document.attachEvent("onreadystatechange", DOMContentLoaded);

        // A fallback to window.onload, that will always work
        window.attachEvent( "onload", yourcallback );

 }

这是 51 行纯 JavaScript 代码,只是为了可靠地注册事件。据我所知,没有更简单的方法。将展示像 jQuery 这样的包装器的优点:它们包装了功能嗅探和丑陋的兼容性问题,以便您可以专注于其他事情。

你能指出我在页面底部谈论怪癖模式和脚本的内容吗?developer.yahoo.com/performance/rules.html是建议您始终将脚本留在页面底部的链接。
2021-03-18 18:58:57
@Juan Mendes:是的,这做了一些表面上相似的事情 - 但内联脚本标签也有它们的怪癖:例如,某些浏览器咳嗽咳嗽时阻止并行下载并且不要忘记整个“让我们在 DOM 仍在加载时修改它”的乐趣。这就是为什么我更愿意使用 $.ready() - Google CDN 上一个缓存良好的库和一个运行良好的函数调用,It Just Works。但是如果你想重新发明自 1997 年以来的所有 JS 黑客,那就继续吧。
2021-03-22 18:58:57
@Piskvor:“但如果你想重新发明自 1997 年以来的所有 JS 黑客,那就继续吧”?这是一个怎样的黑客?我认为这是一个简单(优雅)的解决方案。如果在 body 标记之后放置一个 script 标记,则可以保证 DOM 已准备好,这不是“让我们在 DOM 仍在加载时修改它”
2021-03-26 18:58:57
我得说这是很多复杂的代码,用于知道何时初始化使用 DOM 的脚本......就像我在回答中发布的那样,我只是在 close body 标签之后调用一个初始化函数
2021-04-06 18:58:57
@Juan Mendes:我很抱歉,我在那里有点忘乎所以。
2021-04-14 18:58:57

有史以来最小的 DOMReady 代码。

<html>
  <head>
    <script>
      var ready = function (f) {
        (/complete|loaded|interactive/.test(document.readyState)) ?
            f() :
            setTimeout(ready, 9, f);
      };
    </script>
  </head>
  <body>
    <script>
      ready(function () {
        alert('DOM Ready!');
      });
    </script>
  </body>
</html>
请注意,这eval()在引擎盖下使用但是很酷的把戏人!
2021-03-19 18:58:57
你的情况反过来了。
2021-03-28 18:58:57
快速提问:什么是“r”函数?在 FF 中尝试此操作时出现错误。
2021-04-03 18:58:57
如果您不在 ie 中,请使用“setTimeout(ready, 9, f)”;如果您不在,请使用“setTimeout(function () { ready(f); }, 9)”
2021-04-06 18:58:57

如果您支持 IE9+ 和现代 (2013) 版本的 Chrome、FF、Safari 等,这就是您所需要的。

function ready(event) {
    // your code here
    console.log('The DOM is ready.', event);
    // clean up event binding
    window.removeEventListener('DOMContentLoaded', ready);
}

// bind to the load event
window.addEventListener('DOMContentLoaded', ready);

这是我使用的一种似乎工作可靠的方法

function ready(func) {
  var span = document.createElement('span');
  var ms = 0;
  setTimeout(function() {
    try {
      document.body.appendChild(span);

      document.body.removeChild(span);

      //Still here? Then document is ready
      func();
    } catch(e) {
      //Whoops, document is not ready yet, try again...

      setTimeout(arguments.callee, ms);
    }
  }, ms);
}

很简单,它只是不断尝试将一个空<span>元素附加document.body. 如果文档未“准备好”,则会抛出异常,在这种情况下,它会再次尝试使用新setTimeout调用。一旦没有异常抛出,它就会调用回调函数。

我很高兴听到这种方法是否有任何问题。它对我来说效果很好,但我还没有进行任何流行的 Javascript 框架自然而然的广泛测试。

两个字:内存泄漏。在较旧的浏览器上,随着所有元素的添加和删除,您将疯狂地泄漏内存。另外,您正在 JavaScript 中重新实现忙等待循环(这并不是最有效的语言)。
2021-03-28 18:58:57
我不看。使用此方法,当文档准备好时,元素只会添加和删除一次。即便如此,在超时函数之外的内存中也只创建了一个元素。此外,setTimeout/setInterval0 毫秒延迟与条件 while 循环不同。由于定时器在 JS 中的工作方式,以及本示例超时函数中操作的简单性,性能应该不会受到显着影响。
2021-03-28 18:58:57

我见过很多不同的方法来尝试做到这一点。最简单的方法(我认为是 yahoo 最初建议的)是在 close body 标签之后调用你的初始化函数,有点突兀,但它是一行。