2011-11-09 25 views
11

Tôi đang cố gắng thêm động quy tắc biểu định kiểu css bằng javascript, chẳng hạn như ví dụ 2 here.Khi nào biểu định kiểu được thêm vào document.styleSheets

Nó hoạt động hầu hết thời gian, nhưng có vẻ như là một điều kiện chủng tộc khiến đôi khi gặp lỗi trong (ít nhất) Chrome (15.0.874 và 17.0.933). Nó xảy ra không thường xuyên khi bộ nhớ cache trống (hoặc đã bị xóa).

Đây là những gì tôi đã có thể thu hẹp xuống. Trước tiên, tôi tải biểu định kiểu bên ngoài bằng cách gắn nó vào <head> và sau đó tôi tạo biểu định kiểu mới (nơi tôi sẽ thêm quy tắc). Sau đó tôi in chiều dài document.styleSheets (ngay lập tức và sau 1 giây).

$(function() { 
    // it doesn't happen if this line is missing. 
    $("head").append('<link rel="stylesheet" type="text/css"'+ 
        'href="/css/normalize.css" />'); 

    var stylesheet = document.createElement("style"); 
    stylesheet.setAttribute("type", "text/css"); 
    document.getElementsByTagName('head')[0].appendChild(stylesheet); 

    var b = $('body'); 
    b.append(document.styleSheets.length).append('<br/>'); 
    setTimeout(function() { 
     b.append(document.styleSheets.length).append('<br/>'); 
    }, 1000); 
}); 

(chơi với nó ở http://jsfiddle.net/amirshim/gAYzY/13/)

Khi bộ nhớ cache là rõ ràng, đôi khi nó in 2 sau đó 4 (jsfiddle thêm nó là của riêng 2 file css), có nghĩa là nó không thêm một trong hai phong cách trang tính đến document.styleSheets ngay lập tức ... nhưng có thể chờ tệp bên ngoài tải.

Điều này có được mong đợi không?

Nếu vậy, là Example 2 on MDN (và nhiều người khác ở ngoài đó) bị hỏng? Kể từ dòng 27:

var s = document.styleSheets[document.styleSheets.length - 1]; 

có thể đánh giá với document.styleSheets.length == 0

Lưu ý rằng điều này không xảy ra khi tôi không tải file CSS bên ngoài đầu tiên.

+1

Tôi muốn hỏi bạn kết quả mong muốn của bạn là gì. Trong những trường hợp nào bạn sẽ muốn 'tiêm' một quy tắc vào một tập tin css so với chỉ có nó được viết bên trong tập tin css nơi đầu tiên? – Sotkra

+0

Tôi cũng đang thêm biểu định kiểu động ... nhưng chỉ sau $ (tài liệu) đã được kích hoạt ... –

+1

@Kees: Mã tôi đã cung cấp đang làm mọi thứ trong '$ (tài liệu) .ready'. Đó là những gì '$ (function() {...}); – Amir

Trả lời

4

Nếu JavaScript nằm trong trang bên dưới CSS (hầu như luôn luôn là) trình phân tích cú pháp HTML phải đợi với JS thực thi cho đến khi JS và CSS được tải đầy đủ và phân tích cú pháp vì JS có thể yêu cầu thông tin tạo kiểu (Chrome chỉ làm như vậy khi kịch bản thực sự thực hiện điều này mặc dù). Điều này có hiệu quả làm cho việc tải chặn CSS bên ngoài trong hầu hết các trường hợp. Khi bạn chèn chúng sau này qua JavaScript hoặc không có JS 'trong trang (hoặc tải JS không chặn) CSS tải không đồng bộ nghĩa là chúng được tải và phân tích cú pháp mà không chặn phân tích cú pháp DOM. Chỉ dành cho các tài liệu. Số đếm chỉ được cập nhật sau khi trang tính nằm trong DOM và chỉ xảy ra sau khi được tải và phân tích cú pháp đầy đủ.

Trong trường hợp này, có thể có một số khác biệt về thời gian liên quan. Xem xét hầu hết các trình duyệt chỉ có một số lượng đường ống giới hạn mà chúng tải dữ liệu (một số chỉ có IE6, phần lớn có 6 và một số thậm chí có 12 như IE9) việc tải biểu định kiểu được thêm vào cuối hàng đợi nạp vào. Trình duyệt vẫn tải mọi thứ vì bạn gọi cho bạn hoạt động trên DOMReady. Kết quả nào trong biểu định kiểu không được tải đầy đủ và phân tích cú pháp một giây sau đó, do đó không ảnh hưởng đến document.stylesheets.length.

Và tất cả các ví dụ về biểu định kiểu mà tôi đã chạy trên web giả định rằng dom được phân tích cú pháp đầy đủ và được tải. Biểu định kiểu OffDOM thậm chí không cho phép chèn hoặc kiểm tra quy tắc do thực tế là chúng có thể có quy tắc @import và phải được tải bên ngoài, vì vậy đối với các trình duyệt, rất khó xác định khi nào an toàn để tương tác với trang tính trừ khi chúng được tải đầy đủ và phân tích cú pháp. Biểu định kiểu OffDOM hiển thị thuộc tính trang tính trống nhưng sẽ không cho phép bạn tương tác với nó cho đến khi trang tính được thêm vào DOM.

Tôi luôn tìm thấy nó tốt hơn để chèn biểu định kiểu động và thực hiện tất cả thay đổi trong một trang tính đó và chỉ rời khỏi tài liệu.stylesheets. Điều này có lợi thế lớn là khi bạn ghi đè các kiểu có cùng đặc trưng, ​​bạn sẽ không gặp rắc rối do chèn vào trang tính sai. Vì document.stylesheets là một nodeList trực tiếp, document.stylesheets [2] có thể trỏ đến một trang tính khác mỗi khi bạn gọi hàm (trừ khi được lưu trữ trong một var). Vì vậy, tôi có xu hướng sử dụng trang tính được chèn động và chỉ hoạt động trên trang tính đó.

1

Điều này sẽ giúp: 'When is a stylesheet really loaded'

Đối với 'Ví dụ 2'. Nó sẽ phá vỡ nếu có biểu định kiểu tải khi bạn gọi addStylesheetRules(), tất nhiên là trong Chrome.

+1

Vì vậy, Ví dụ 2 không phải lúc nào cũng hoạt động. tức là nếu tôi (hoặc một thư viện js khác) chỉ cần thêm một biểu định kiểu bên ngoài trước khi gọi 'addStylesheetRules()'. – Amir

Các vấn đề liên quan