1.首先要了解頁面的結構(包含哪些元素?哪些計算機語言能夠在頁面中運行?)
(1)html
? ? ? ? ?不僅可以包含文字,還可以包含圖片、鏈接,甚至音樂、程序等非文字元素的標記語言
? ? ? ? ?(展示給用戶,不能太單調,css)
(2)css
? ? ? ? ?是一種用來表現HTML的計算機語言,能使HTML頁面變得更加美觀
? ? ? ? ?(要展示給用戶光漂亮是不夠的,用戶還要能夠動態的操作HTML頁面,也就是讓瀏覽器和用戶之間的交互不僅僅是用戶能瀏覽html中的內容,還要能對html頁面操作,JavaScript)
(3)JavaScript
? ? ? ? ?用來給HTML網頁增加動態功能、交互行為
? ? ? ? ?是一種解釋性腳本語言(不進行預編譯)
? ? ? ? ?目前我們熟悉的語言Java、JavaScript、C、C++,都屬于高級編程語言
? ? ? ? ?①計算機不能理解高級語言,也就不能直接執行高級語言了
? ? ? ? ?②計算機只能直接理解機器語言,所以任何語言,都必須將其翻譯成機器語言,計算機才能運行高級語言編寫的程序
? ? ? ? ?③翻譯的方式有兩種,一個是編譯,一個是解釋。
? ? ? ? ? ? ? 1)編譯:Java語言的運行先經過編譯,但是JAVA語言的編譯不是直接編譯成計算機能識別的語言,而是編譯成JAVA虛擬機能識別的class文件
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? JAVA語言就是典型的翻譯方式為編譯的編程語言,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 雖然不是編譯成計算機能直接識別的語言,但是同其他以編譯為翻譯方式的高級編程語言的原理大體上是相同的。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 最明顯:C/C++,可以編譯成二進制代碼,以可執行文件的形式存在(exe文件)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 都是先編譯再運行,而且是一次編譯到處運行,效率非常高。(只需要在第一次運行的時候編譯一次)
? ? ? ? ? ? ? 2)解釋:解釋性腳本語言的程序不需要編譯,解釋性腳本語言在運行程序的時候才翻譯
? ? ? ? ? ? ? ? ? ? ? ? ? ? ??解釋性腳本語言有專門的解釋器來負責解釋,不過每次都需要翻譯,效率比較低。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? JavaScript?就是一種解釋性腳本語言
? ? ? ? ?④JavaScript也有自己專門的解釋器——JavaScript引擎,它存在于瀏覽器端,作為瀏覽器的一部分
一句話:html(超文本標記語言)、css(層疊 樣式表)、JavaScript腳本語言這三樣東西在瀏覽器端相互配合、相輔相成形成了比較成熟的前端界面
(4)這三樣東西在HTML頁面中的位置
html的基本結構? ? ? ? ??
<html> <head> <!-- 頭部中包含的標記是頁面的標題、序言、說明等內容,它本身不作為內容來顯示,但影響網頁顯示的效果 --> </head> <body> <!-- 顯示實際內容 --> </body> </html>
①html:貫穿整個頁面
? ? ? ? ②css:三種聲明方式
? ? ? ? ? ? ? ? ? ? ?外聯樣式表:在head便簽中 用link標簽的href屬性來引用后綴名為.css的css樣式文件
? ? ? ? ? ? ? ? ? ? ?內聯樣式表:在head標簽下的style標簽中,選擇器 + 樣式聲明
? ? ? ? ? ? ? ? ? ? ?內部樣式表:在標簽的style屬性中添加css樣式聲明
? ? ? ? ③JavaScript:在<script>標簽中,可以在head標簽中,也可以在body標簽中(區別一會再說)
小總結:以上內容總結出一句話:目前為止,在整個html頁面中,可以寫html代碼、css樣式、JS腳本語言
? ?????位置:html貫穿整個頁面,css可以定義在head頭標簽中,也可以在定義在html標簽的屬性中
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?JavaScript定義在<script>標簽中,<script>標簽既能在head標簽中定義也能在body標簽中定義
問題1:JQuery、EasyUI也可以寫在html頁面中
? ? ? ? ? ? ?jQuery是一個快速、簡潔的JavaScript框架(本質上也是JavaScript)
? ? ? ? ? ? ?EasyUI:類庫中都是以 .css和.js結尾的文件。別人寫好的css樣式和JavaScript(本質上也是css和JavaScript)
? ? ? ? ? ? ?所以追其根源,html頁面中就是 html、css、JavaScript
問題2:jsp中能編寫Java代碼
? ? ? ? ? ? ?jsp是特殊的Servlet,本質是Java,是Java就要運行在服務器端,瀏覽器是不能解析Java代碼的
? ? ? ? ? ? ?為什么用瀏覽器訪問jsp時能在瀏覽器端顯示呢?
? ? ? ? ? ? ?分兩種情況:
? ? ? ? ? ? ?①對于html文件,當我們用瀏覽器訪問時能自動解析,解析完畢就會將內容展示在瀏覽器上
? ? ? ? ? ? ?②對于jsp,當我們用瀏覽器訪問時,我們寫好的jsp文件會生成.java文件,服務器運行JAVA文件,會把jsp中編寫的html代碼,發送給瀏覽器
? ? ? ? ? ? ? ? ?可以這樣理解,我們編寫的HTML文件被瀏覽器直接解析
? ? ? ? ? ? ? ? ?而我們編寫的jsp,是借助JAVA代碼將html代碼發給瀏覽器,瀏覽器再解析
? ? ? ? ? ? ? ? ?本質上都是瀏覽器解析html代碼(這里的html代碼,包括剛才說的html、css、JavaScript)
2.加載順序
<html> <head> <!-- 引用外部JS文件 --> <script src="..........."></script> <!--引用外部css樣式 --> <link href="............."/> <style> .............. </style> <script> .............. </script> </head> <body> <script> .............. </script> </body> </html>
從上到下運行,先解析head標簽中的代碼,
(1)head標簽中會包含一些引用外部文件的代碼,從開始運行就會下載這些被引用的外部文件
? ? ? ? ?當遇到script標簽的時候
? ? ? ? ?瀏覽器暫停解析(不是暫停下載),將控制權交給JavaScript引擎(解釋器)
如果?<script>標簽引用了外部腳本,就下載該腳本,否則就直接執行,執行完畢后將控制權交給瀏覽器渲染引擎
(2)當head中代碼解析完畢,會開始解析body中的代碼
? ? ? ? ?如果此時head中引用的外部文件沒有下載完,將會繼續下載
? ? ? ? ?瀏覽器解析body代碼中的元素,會按照head中聲明一部分樣式去解析
? ? ? ? ?如果此時遇到body標簽中的<script>,同樣會將控制權交給JavaScript引擎來解析JavaScript
? ? ? ? ?解析完畢后將控制權交還給瀏覽器渲染引擎。
? ? ? ? ?當body中的代碼全部執行完畢、并且整個頁面的css樣式加載完畢后,css會重新渲染整個頁面的html元素。
(3)按照之前的描述,<script>寫到body標簽內靠后比較好,
? ? ? ? ?因為JavaScript 會操作html元素,?如果在body加載完之前寫JavaScript?會造成JavaScript?找不到頁面元素
? ? ? ? ?但是我們經常將<script>寫到head中,body中不會有大量的js代碼,body中的html代碼結構會比較清晰
? ? ? ? ?window.onload: 等待頁面中的所有內容加載完畢之后才會執行
? ? ? ? ?$(document).ready(): 頁面中所有DOM結構繪制完畢之后就能夠執行
? ? ? ? ?可以這樣理解:window.onload 和?$(document).ready()/$(function(){}); 相當于 ?寫在body 內 ?最靠后的<script> 代碼段
DOM文檔的加載順序是由上而下的順序加載
1、DOM加載到link標簽
css文件的加載是與DOM的加載并行的,也就是說,css在加載時Dom還在繼續加載構建,而過程中遇到的css樣式或者img,則會向服務器發送一個請求,待資源返回后,將其添加到dom中的相對應位置中;
2、DOM加載到script標簽
由于js文件不會與DOM并行加載,因此需要等待js整個文件加載完之后才能繼續DOM的加載,倘若js腳本文件過大,則可能導致瀏覽器頁面顯示滯后,出現“假死”狀態,這種效應稱之為“阻塞效應”;會導致出現非常不好的用戶體驗;
而這個特性也是為什么在js文件中開頭需要$(document).ready(function(){})或者(function(){})或者window.onload,即是讓DOM文檔加載完成之后才執行js文件,這樣才不會出現查找不到DOM節點等問題;
js阻塞其他資源的加載的原因是:瀏覽器為了防止js修改DOM樹,需要重新構建DOM樹的情況出現;
3、解決方法
前提,js是外部腳本;
在script標簽中添加 defer=“ture”,則會讓js與DOM并行加載,待頁面加載完成后再執行js文件,這樣則不存在阻塞;
在scirpt標簽中添加 async=“ture”,這個屬性告訴瀏覽器該js文件是異步加載執行的,也就是不依賴于其他js和css,也就是說無法保證js文件的加載順序,但是同樣有與DOM并行加載的效果;
同時使用defer和async屬性時,defer屬性會失效;
可以將scirpt標簽放在body標簽之后,這樣就不會出現加載的沖突了。
CSS樣式為什么放在head中,而不放在body底部
放在body底部,瀏覽器會快速閃一下"css樣式加載順序", 這時的樣式是瀏覽器默認樣式,說明了瀏覽器已經渲染過一次;等底部css文件加載完,又重新渲染一遍;放在head中,在加載html前,加載完了css文件,這時渲染一次就OK了。
結論:
放在body底部,在DOM Tree構建完成之后開始構建render Tree,計算布局然后繪制網頁,等css文件加載后,開始構建CSSOM Tree,并和DOM Tree一起構建render Tree,再次計算布局重新繪制;
放在head中,先加載css,構建CSSOM,同時構建DOM Tree,CSSOM和DOM Tree構建完成后,構建render Tree,進行計算布局繪制網頁。
總體來看,放在body底部要比放在head中多一次構建render Tree,多一次計算布局,多一次繪制,從性能方面來看,不如放在head中。再次,放在body底部網頁會閃現默認樣式的DOM結構,用戶體驗不好。