Tương đương không phải của jQuery là '$ (tài liệu). Đã ()' là gì?


444

Tương đương không phải của jQuery là $(document).ready()gì?


4
Nếu bạn muốn sao chép $(document).ready()sự kiện của jQuery mà không sử dụng bất kỳ thư viện nào, hãy xem cái này: stackoverflow.com/questions/1795089/ mẹo
CMS

@OP: xem trang 89 của Kỹ thuật JavaScript chuyên nghiệp để biết cách triển khai JavaScript của vanilla $(document).ready()- Books.google.com/ . Nó cũng sử dụng addEventsự trừu tượng ràng buộc sự kiện được viết bởi Dean Edwards, mã của nó cũng có trong cuốn sách :)
Russ Cam

Câu trả lời:


75

Điều tốt đẹp $(document).ready()là nó bắn trước đó window.onload. Hàm tải chờ cho đến khi mọi thứ được tải, bao gồm cả tài sản và hình ảnh bên ngoài. $(document).readytuy nhiên, kích hoạt khi cây DOM hoàn thành và có thể được thao tác. Nếu bạn muốn đạt được DOM sẵn sàng, không có jQuery, bạn có thể kiểm tra thư viện này. Ai đó chỉ trích xuất readymột phần từ jQuery. Nó đẹp và nhỏ và bạn có thể thấy nó hữu ích:

sẵn sàng tại Google Code


4
Mạng mã DomReady! thông qua @CMS trên github: github.com/cms/dom
yet / network

44
Điều này không trả lời câu hỏi cũng như không hiển thị bất kỳ mã không phải jQuery nào. Làm thế nào mà nó nhận được rất nhiều upvote?
Daniel W.

3
@DanielW. Bởi vì nó đơn giản và thiết thực. Hầu hết chúng ta đến đây để tìm cách đảm bảo DOM sẵn sàng được sử dụng bởi mã javascript.
abarazal

Vâng, nhưng một số người trong chúng tôi đã đến đây để có câu trả lời thực sự.
Slbox

611

Điều này hoạt động hoàn hảo, từ ECMA

document.addEventListener("DOMContentLoaded", function() {
  // code...
});

Cái window.onloadnày không bằng JQuery $(document).ready$(document).readychỉ đợi cây DOM trong khi window.onloadkiểm tra tất cả các thành phần bao gồm cả tài sản và hình ảnh bên ngoài.

EDIT : Đã thêm IE8 trở lên tương đương, nhờ vào sự quan sát của Jan Derk . Bạn có thể đọc nguồn của mã này trên MDN tại liên kết này :

// alternative to DOMContentLoaded
document.onreadystatechange = function () {
    if (document.readyState == "interactive") {
        // Initialize your application or run some code.
    }
}

Có những lựa chọn khác ngoài "interactive". Xem liên kết MDN để biết chi tiết.


Đồng ý với Benjamin. Bạn không thể đơn giản sử dụng Đính kèm. Ví dụ: trong Chrome bạn nhận được: Uncaught TypeError: document.attachEvent không phải là một chức năng. Sử dụng câu trả lời được liên kết bởi Jan Derk.
Manuel Arwed Schmidt

9
Điều gì nếu tài liệu đã được tải khi tập lệnh này được gọi? Sẽ không có gì xảy ra cả :(
oriadam

8
@Deerloper Không, chỉ cần thử nó trên bảng điều khiển Chrome - không có gì xảy ra: document.addEventListener("DOMContentLoaded",function(){console.log(123)})hãy thử ngay bây giờ
oriadam

2
Hỗ trợ DOMContentLoaded trong trình duyệt: caniuse.com/domcontentloaded
Guillaume Husta

1
@elliottregan đó là sự thật Tôi xóa bình luận để tránh làm ô nhiễm chủ đề này. Tôi đề nghị tất cả các bạn cũng làm như vậy :) Và hãy để một bình luận nếu cần chỉ ra nhận xét nếu cần. Vì đó là một phần phụ vì nó vượt xa các câu hỏi OC
sospedra

43

Một điều nhỏ tôi đặt lại với nhau

dom yet.js

(function(exports, d) {
  function domReady(fn, context) {

    function onReady(event) {
      d.removeEventListener("DOMContentLoaded", onReady);
      fn.call(context || exports, event);
    }

    function onReadyIe(event) {
      if (d.readyState === "complete") {
        d.detachEvent("onreadystatechange", onReadyIe);
        fn.call(context || exports, event);
      }
    }

    d.addEventListener && d.addEventListener("DOMContentLoaded", onReady) ||
    d.attachEvent      && d.attachEvent("onreadystatechange", onReadyIe);
  }

  exports.domReady = domReady;
})(window, document);

Làm thế nào để sử dụng nó

<script src="domready.js"></script>
<script>
  domReady(function(event) {
    alert("dom is ready!");
  });
</script>

Bạn cũng có thể thay đổi bối cảnh trong đó cuộc gọi lại chạy bằng cách chuyển một đối số thứ hai

function init(event) {
  alert("check the console");
  this.log(event);
}

domReady(init, console);

2
Cảm ơn bạn. Tôi thích thực tế là nó tương thích ngược. Tiến về phía trước không có nghĩa là chỉ để lại những người kém may mắn hơn phía sau. Không thể sử dụng trình duyệt hiện đại (vì bất kỳ lý do gì) là điều không may ...
CO

28

Bây giờ là năm 2018, đây là một phương pháp nhanh chóng và đơn giản.

Điều này sẽ thêm một trình lắng nghe sự kiện, nhưng nếu nó đã được kích hoạt, chúng tôi sẽ kiểm tra xem dom đang ở trạng thái sẵn sàng hay chưa. Điều này có thể kích hoạt trước hoặc sau khi tài nguyên phụ đã tải xong (hình ảnh, bảng định kiểu, khung, v.v.).

function domReady(fn) {
  // If we're early to the party
  document.addEventListener("DOMContentLoaded", fn);
  // If late; I mean on time.
  if (document.readyState === "interactive" || document.readyState === "complete" ) {
    fn();
  }
}

domReady(() => console.log("DOM is ready, come and get it!"));

Bài đọc thêm


Cập nhật

Dưới đây là một số trình trợ giúp tiện ích nhanh bằng cách sử dụng Nhập & Xuất ES6 tiêu chuẩn mà tôi đã viết bao gồm TypeScript. Có lẽ tôi có thể đi xung quanh để biến chúng thành một thư viện nhanh có thể được cài đặt vào các dự án như một sự phụ thuộc.

JavaScript

export const domReady = (callBack) => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', callBack);
  }
  else {
    callBack();
  }
}

export const windowReady = (callBack) => {
  if (document.readyState === 'complete') {
    callBack();
  }
  else {
    window.addEventListener('load', callBack);
  }
}

TypeScript

export const domReady = (callBack: () => void) => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', callBack);
  }
  else {
    callBack();
  }
}

export const windowReady = (callBack: () => void) => {
  if (document.readyState === 'complete') {
    callBack();
  }
  else {
    window.addEventListener('load', callBack);
  }
}

Hứa

export const domReady = new Promise(resolve => {
  if (document.readyState === "loading") {
    document.addEventListener('DOMContentLoaded', resolve);
  }
  else {
    resolve();
  }
});

export const windowReady = new Promise(resolve => {
  if (document.readyState === 'complete') {
    resolve();
  }
  else {
    window.addEventListener('load', resolve);
  }
});

16

Theo http://youmightnotneedjquery.com/# đã có một sự thay thế tốt đẹp vẫn hoạt động với IE8 là

function ready(fn) {
  if (document.readyState != 'loading') {
    fn();
  } else if (document.addEventListener) {
    document.addEventListener('DOMContentLoaded', fn);
  } else {
    document.attachEvent('onreadystatechange', function() {
      if (document.readyState != 'loading')
        fn();
    });
  }
}

// test
window.ready(function() {
    alert('it works');
});

Cải thiện : Cá nhân tôi cũng sẽ kiểm tra xem loại của fnlà một chức năng. Và như @elliottregan đề nghị loại bỏ người nghe sự kiện sau khi sử dụng.

Lý do tôi trả lời câu hỏi này muộn là vì tôi đã tìm kiếm câu trả lời này nhưng không thể tìm thấy nó ở đây. Và tôi nghĩ rằng đây là giải pháp tốt nhất.


1
Vâng, đây là câu trả lời tốt nhất theo ý kiến ​​của tôi. Dễ đọc và nó thực thi mã ngay cả khi DOM đã được tải. Điều duy nhất tôi muốn thêm là xóa trình phát sự kiện sau khi sự kiện được kích hoạt.
elliottregan

14

Có một sự thay thế dựa trên các tiêu chuẩn, DOMContentLoaded, được hỗ trợ bởi hơn 90% + trình duyệt, nhưng không phải IE8 (Vì vậy, JQuery sử dụng mã dưới đây để hỗ trợ trình duyệt) :

document.addEventListener("DOMContentLoaded", function(event) { 
  //do work
});

Hàm riêng của jQuery phức tạp hơn nhiều so với window.onload, như được mô tả dưới đây.

function bindReady(){
    if ( readyBound ) return;
    readyBound = true;

    // Mozilla, Opera and webkit nightlies currently support this event
    if ( document.addEventListener ) {
        // Use the handy event callback
        document.addEventListener( "DOMContentLoaded", function(){
            document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
            jQuery.ready();
        }, 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", function(){
            if ( document.readyState === "complete" ) {
                document.detachEvent( "onreadystatechange", arguments.callee );
                jQuery.ready();
            }
        });

        // If IE and not an iframe
        // continually check to see if the document is ready
        if ( document.documentElement.doScroll && window == window.top ) (function(){
            if ( jQuery.isReady ) return;

            try {
                // If IE is used, use the trick by Diego Perini
                // http://javascript.nwbox.com/IEContentLoaded/
                document.documentElement.doScroll("left");
            } catch( error ) {
                setTimeout( arguments.callee, 0 );
                return;
            }

            // and execute any waiting functions
            jQuery.ready();
        })();
    }

    // A fallback to window.onload, that will always work
    jQuery.event.add( window, "load", jQuery.ready );
}

1
JQuery mới bỏ hỗ trợ cho các trình duyệt cũ hơn và bây giờ chúng chỉ có DOMContentLoadedloadcác sự kiện sử dụng addEventListener, và đầu tiên, lửa loại bỏ cả hai trình nghe, vì vậy nó không kích hoạt hai lần.
jcubic

8

Trong JavaScript vanilla đơn giản, không có thư viện? Đó là một lỗi. $chỉ đơn giản là một định danh và không được xác định trừ khi bạn xác định nó.

jQuery định nghĩa $là "đối tượng mọi thứ" của riêng nó (còn được gọi là jQueryvì vậy bạn có thể sử dụng nó mà không xung đột với các thư viện khác). Nếu bạn không sử dụng jQuery (hoặc một số thư viện khác định nghĩa nó), thì $sẽ không được xác định.

Hoặc bạn đang hỏi những gì tương đương trong JavaScript đơn giản? Trong trường hợp đó, bạn có thể muốn window.onload, điều này không chính xác tương đương, nhưng là cách nhanh nhất và dễ nhất để tiến gần đến hiệu ứng tương tự trong JavaScript vanilla.


39
Đối với nhiều người phản đối câu trả lời này (và những người khác bên dưới): khi câu hỏi này được hỏi, nó chỉ đơn giản nói: "$ (tài liệu). Đã () trong javascript là gì? Không phải là câu hỏi." Có vẻ như anh ta đang hỏi điều đó có nghĩa là gì trong JavaScript vanilla đơn giản mà không tải jQuery. Trong câu trả lời của mình, tôi đã cố gắng trả lời câu hỏi đó, cũng như đưa ra câu trả lời dễ dàng gần nhất cho JavaScript vanilla đơn giản không có jQuery hoặc các thư viện khác trong trường hợp đó là ý anh. Lưu ý rằng tất cả bối cảnh bổ sung đã được thêm vào bởi những người khác đoán xem câu hỏi đang hỏi là gì, không phải là poster gốc.
Brian Campbell

5

Cách dễ nhất trong các trình duyệt gần đây là sử dụng GlobalEventHandlers , onDOMContentLoaded , onload , onloadeddata (...)

onDOMContentLoaded = (function(){ console.log("DOM ready!") })()

onload = (function(){ console.log("Page fully loaded!") })()

onloadeddata = (function(){ console.log("Data loaded!") })()

Sự kiện DOMContentLoaded được kích hoạt khi tài liệu HTML ban đầu đã được tải và phân tích cú pháp hoàn toàn, không cần chờ biểu định kiểu, hình ảnh và khung con để tải xong. Chỉ nên sử dụng tải sự kiện rất khác nhau để phát hiện trang được tải đầy đủ. Đó là một lỗi cực kỳ phổ biến khi sử dụng tải trong đó DOMContentLoaded sẽ phù hợp hơn nhiều, vì vậy hãy thận trọng.

https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded

Hàm được sử dụng là IIFE, rất hữu ích trong trường hợp này, vì nó tự kích hoạt khi sẵn sàng:

https://en.wikipedia.org/wiki/Immediately-invoking_feft_expression

Rõ ràng là thích hợp hơn để đặt nó ở cuối của bất kỳ kịch bản.

Trong ES6, chúng ta cũng có thể viết nó dưới dạng hàm mũi tên:

onload = (() => { console.log("ES6 page fully loaded!") })()

Cách tốt nhất là sử dụng các phần tử DOM, chúng ta có thể đợi bất kỳ biến nào sẵn sàng, điều đó kích hoạt IIFE có mũi tên.

Các hành vi sẽ giống nhau, nhưng với tác động bộ nhớ ít hơn.

footer = (() => { console.log("Footer loaded!") })()
<div id="footer">

Trong nhiều trường hợp, đối tượng tài liệu cũng được kích hoạt khi sẵn sàng , ít nhất là trong trình duyệt của tôi. Cú pháp sau đó rất hay, nhưng nó cần kiểm tra thêm về tính tương thích.

document=(()=>{    /*Ready*/   })()

Có thể kích hoạt IIFE trước khi DOM kết thúc tải các phần tử sau nó không?
CTS_AE

Chắc chắn, nó chỉ là một chức năng, một chức năng ẩn danh, trong một bao đóng.
NVRM

0

Phần thân onLoad cũng có thể là một sự thay thế:

<html>
<head><title>Body onLoad Exmaple</title>

<script type="text/javascript">
    function window_onload() {
        //do something
    }
</script>

</head>
<body onLoad="window_onload()">

</body>
</html>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.