2008-09-18 48 views
36

tôi đã kịch bản sau đây, nơi document.writeline đầu tiên và thứ ba là tĩnh và thứ hai được tạo ra:JavaScript của document.write Inline Script Execution tự

<script language="javascript" type="text/javascript"> 
document.write("<script language='javascript' type='text/javascript' src='before.js'><\/sc" + "ript>"); 
document.write("<script language='javascript' type='text/javascript'>alert('during');<\/sc" + "ript>"); 
document.write("<script language='javascript' type='text/javascript' src='after.js'><\/sc" + "ript>"); 
</script> 

Firefox và Chrome sẽ hiển thị trước, trongsau, trong khi Internet Explorer đầu tiên hiển thị trong thời gian và chỉ khi đó nó hiển thị trướcsau.

Tôi đã xem qua số an article that states rằng tôi không phải là người đầu tiên gặp phải điều này, nhưng điều đó hầu như không làm tôi cảm thấy tốt hơn.

Có ai biết cách tôi có thể đặt thứ tự xác định trong tất cả các trình duyệt hay hack IE hoạt động giống như tất cả các trình duyệt khác không?

Hãy cẩn thận: Đoạn mã là bản giới thiệu rất đơn giản. Nó được tạo ra trên máy chủ và kịch bản thứ hai là điều duy nhất thay đổi. Đó là một kịch bản dài và lý do có hai kịch bản trước và sau khi nó được để trình duyệt sẽ lưu trữ chúng và phần động của mã sẽ càng nhỏ càng tốt. Nó cũng có thể xuất hiện nhiều lần trong cùng một trang với mã được tạo khác nhau.

+0

Phải đọc: http://html5rocks.com/en/tutorials/speed/script-loading – Pacerier

Trả lời

5

Tôi đã tìm thấy một câu trả lời hơn theo ý thích của tôi:

<script language="javascript" type="text/javascript"> 
document.write("<script language='javascript' type='text/javascript' src='before.js'><\/sc" + "ript>"); 
document.write("<script defer language='javascript' type='text/javascript'>alert('during');<\/sc" + "ript>"); 
document.write("<script defer language='javascript' type='text/javascript' src='after.js'><\/sc" + "ript>"); 
</script> 

này sẽ trì hoãn việc tải của cả hai trongsau cho đến khi trang đã tải xong.

Tôi nghĩ rằng điều này là tốt như tôi có thể nhận được. Hy vọng rằng, ai đó sẽ có thể đưa ra một câu trả lời tốt hơn.

+6

Internet Explorer chạy tập lệnh nội tuyến trước các tập lệnh bên ngoài. Để có được thứ tự nhất quán, hãy di chuyển mã nội tuyến sang tệp bên ngoài. –

1

Trang trình bày 25/26 của this presentation nói về đặc điểm của các phương pháp khác nhau để chèn tập lệnh. Nó cho thấy rằng IE là trình duyệt duy nhất sẽ thực thi các script đó theo thứ tự. Tất cả các trình duyệt khác sẽ thực thi chúng theo thứ tự mà chúng tải xong. Ngay cả IE sẽ không thực hiện chúng theo thứ tự nếu một hoặc nhiều có js nội tuyến thay vì một src.

Một trong những phương pháp được đề xuất là để chèn một phần tử DOM mới:

var se1 = document.createElement('script'); 
se1.src = 'a.js'; 

var se2 = document.createElement('script'); 
se2.src = 'b.js'; 

var se3 = document.createElement('script'); 
se3.src = 'c.js'; 

var head = document.getElementsByTagName('head')[0] 
head.appendChild(se1); 
head.appendChild(se2); 
head.appendChild(se3); 

Để làm cho phần kịch bản thứ hai được tạo ra bạn có thể sử dụng một kịch bản để tạo ra nội dung đó và vượt qua các thông số:

se2.src = 'generateScript.php?params=' + someParam; 

EDIT: Mặc dù những gì bài báo tôi nói, thử nghiệm của tôi cho thấy hầu hết các trình duyệt sẽ thực thi kịch bản lệnh document.write của bạn nếu chúng có src, vì vậy trong khi tôi nghĩ phương pháp trên được ưu tiên, bạn có thể làm điều này cũng như:

<script language="javascript" type="text/javascript"> 
document.write("<script type='text/javascript' src='before.js'><\/sc" + "ript>"); 
document.write("<script type='text/javascript' src='during.php?params=" + params + "'><\/sc" + "ript>"); 
document.write("<script type='text/javascript' src='after.js'><\/sc" + "ript>"); 
</script> 

CHỈNH SỬA LẠI (trả lời nhận xét cho chính tôi và những người khác): Bạn đã tạo tập lệnh trên trang của mình. Bất cứ điều gì bạn đang làm đều có thể được chuyển sang một kịch bản lệnh phía máy chủ khác, tạo ra cùng một khối mã. Nếu bạn cần các tham số trên trang của bạn thì chuyển chúng vào tập lệnh trong chuỗi truy vấn.

Ngoài ra, bạn có thể sử dụng phương pháp này tương tự nếu như bạn đề nghị, bạn đang tạo ra inline kịch bản nhiều lần:

<script language="javascript" type="text/javascript"> 
document.write("<script type='text/javascript' src='before.js'><\/sc" + "ript>"); 
document.write("<script type='text/javascript' src='during.php?params=" + params1 + "'><\/sc" + "ript>"); 
document.write("<script type='text/javascript' src='during.php?params=" + params2 + "'><\/sc" + "ript>"); 
document.write("<script type='text/javascript' src='during.php?params=" + params3 + "'><\/sc" + "ript>"); 
document.write("<script type='text/javascript' src='after.js'><\/sc" + "ript>"); 
</script> 

Tuy nhiên, điều này đang bắt đầu trông như thể bạn đang tiếp cận này một cách sai lầm . Nếu bạn đang tạo ra một khối lớn mã nhiều lần thì có lẽ bạn nên thay thế nó bằng một hàm js duy nhất và gọi nó với các tham số khác nhau ...

+0

'trong' là một mảnh rất dài của kịch bản, vì vậy tôi có thể' t tóm tắt nó thành một yêu cầu nhận đơn giản ... –

+0

@Omer: Bạn đã tóm tắt nó thành một "yêu cầu nhận đơn giản" ... Làm thế nào bạn tạo ra nó ngay bây giờ để đưa nó vào nội tuyến? Bất cứ điều gì bạn đang làm bây giờ bạn có thể làm trên một trang khác nhưng chỉ trả lại js và không phải phần còn lại của trang. – Prestaul

+0

mã trình diễn mà tôi đưa ra là một sự repro rất đơn giản của vấn đề. mã tôi đã viết là mã được tạo và tệp bao gồm để trình duyệt sẽ lưu chúng và cần ít thời gian hơn để tải trang. –

1

OK ... trong ...

// During.js 
during[fish](); 

sau ...

// After.js 
alert("After"); 
fish++ 

HTML

<!-- some html --> 
<script language="javascript" type="text/javascript"> 
document.write("<script language='javascript' type='text/javascript' src='before.js'></sc" + "ript>"); 
document.write("<script language='javascript' type='text/javascript'>during[" + fish + "] = function(){alert('During!' + fish);}</sc" + "ript>"); 
document.write("<script language='javascript' type='text/javascript' src='during.js'></sc" + "ript>"); 
document.write("<script language='javascript' type='text/javascript' src='after.js'></sc" + "ript>"); 
</script> 
<!-- some other html --> 
<script language="javascript" type="text/javascript"> 
document.write("<script language='javascript' type='text/javascript' src='before.js'></sc" + "ript>"); 
document.write("<script language='javascript' type='text/javascript'>during[" + fish + "] = function(){alert('During!' + fish);}</sc" + "ript>"); 
document.write("<script language='javascript' type='text/javascript' src='during.js'></sc" + "ript>"); 
document.write("<script language='javascript' type='text/javascript' src='after.js'></sc" + "ript>"); 
</script> 

tôi nghiêng để đồng ý về cách thức này đang bắt đầu ngửi thấy, mặc dù. Đặc biệt, tại sao bạn không thể mã hóa "trong" thành tệp js được tạo động và chèn tệp đó?

Lưu ý rằng tập lệnh được tạo động sẽ đi bên trong chức năng trong giây thứ hai document.write.
Thử nghiệm trong FF2, IE7

24

Không, đây là hành vi của Internet Explorer.

Nếu bạn đính kèm tập lệnh động, IE, Firefox và Chrome sẽ tải xuống tập lệnh theo cách không đồng bộ.

Firefox và Chrome sẽ đợi cho đến khi tất cả yêu cầu không đồng bộ trở lại và sau đó sẽ thực thi các tập lệnh theo thứ tự được đính kèm trong DOM nhưng IE thực thi các tập lệnh theo thứ tự chúng được trả về trên dây.

Vì cảnh báo mất ít thời gian hơn để "truy xuất" hơn tệp javascript bên ngoài, điều đó có khả năng giải thích hành vi mà bạn đang thấy.

Từ Kristoffer Henriksson của post on the subject of asynchronous script loading:

Trong kịch bản này của IE và Firefox sẽ tải về cả hai kịch bản nhưng Internet Explorer cũng sẽ thực hiện chúng trong để họ hoàn thành tải trong trong khi Firefox tải chúng không đồng bộ nhưng vẫn thực hiện chúng theo thứ tự chúng được đính kèm trong các mẫu DOM.

Trong Internet Explorer điều này có nghĩa kịch bản của bạn không thể có dependancies trên nhau như trình tự thực hiện sẽ thay đổi tùy theo mạng giao thông, lưu trữ, vv

Xem xét sử dụng một bộ nạp Javascript. Nó sẽ cho phép bạn chỉ định các phụ thuộc kịch bản và thứ tự thực thi trong khi cũng tải các kịch bản của bạn một cách không đồng bộ cho tốc độ cũng như làm mịn một số khác biệt của trình duyệt.

Đây là tổng quan khá tốt về một vài trong số chúng: Essential JavaScript: the top five script loaders.

Tôi đã sử dụng cả hai RequireJS và LabJS. Theo ý kiến ​​của tôi, LabJS là một chút ít ý kiến.

0

Mã để cung cấp:

<script language="javascript" type="text/javascript"> 
document.write("<script language='javascript' type='text/javascript'>function callGeneratedContent() { alert('during'); }<\x2Fscript>"); 
document.write("<script language='javascript' type='text/javascript' src='before.js'><\x2Fscript>"); 
document.write("<script language='javascript' type='text/javascript' src='after.js'><\x2Fscript>"); 
</script> 

Trong before.js:

alert("Before"); 
callGeneratedContent(); 

Trong sau.js:

alert("After"); 

Bạn phải đặt dòng được tạo trước, nếu không FF sẽ khiếu nại vì nó thực thi before.js trước khi xem định nghĩa hàm.

+0

vui lòng xem trước câu trả lời của Dustman. –

1

Bạn có thể bắt buộc thực hiện bảo mật bằng cách xác định các sự kiện "onload" (hoặc tương tự) trên các tập lệnh và chèn một sự kiện tiếp theo vào hàm sự kiện. Nó không phải là tầm thường, nhưng có rất nhiều ví dụ trên mạng, đây là một ví dụ.

http://www.phpied.com/javascript-include-ready-onload/

Tôi nghĩ rằng các thư viện phổ biến như jQuery hay nguyên mẫu có thể giúp với điều này.

0

Làm thế nào về điều đó:

<script> 
document.write("<script src='before.js'><\/script>"); 
</script> 

<script > 
document.write("<script>alert('during');<\/script>"); 
</script> 

<script> 
document.write("<script src='after.js'><\/script>"); 
</script> 
Các vấn đề liên quan