大家好,有些詞兒,程序員之間雖然天天說,彼此之間心照不宣,但是在面對一些非技術(shù)的產(chǎn)品同學的時候,對方卻不一定能一下子就get到點。這個系列的文章就是為了解決這種尷尬的,理想的效果是,只要一提起這些詞兒,你腦海中就會出現(xiàn)一幅圖或者一段精妙的解釋,那我們就成功了。
今天Java培訓班講解的詞兒是DOM,是程序員里面最基礎、最常用的一個東西。它的全稱是文檔對象模型(document Object
Model),光看名字太抽象,簡單解釋一下。我們知道,一個網(wǎng)頁,其實就是一個html文件,經(jīng)過瀏覽器的解析,最終呈現(xiàn)在用戶面前。html語言我們也講過,是由很多標簽組成的,像這樣:
里面的head、body就是標簽。這些標簽不是隨意擺放的,他們有自己的規(guī)則。首先它們是嵌套的,一層套一層,比如html套body,body又套p標簽。其次,每一層,可以同時存在很多標簽,比如head和body就是一層的,他們被外面的html套著。這樣的結(jié)構(gòu)很像我們電腦里的文件夾,「我的電腦」是最外面的一層,里面套著CDEF盤,每個盤里又有很多文件夾,文件夾里又有文件夾,最后才是很多具體的文件。
為什么要按照這種結(jié)構(gòu)來組織呢?其實就是方便解析和查詢。解析的時候,從外到里,循序漸進,好比按照圖紙蓋房子,先蓋圍墻,再蓋走廊,最后才是臥室。查詢的時候,會有一條明確的路線,比如D盤-->島國文化交流-->影視作品-->蒼老師.avi,這樣一層一層的縮小范圍,查找效率會非常高。
所以,瀏覽器在解析html文檔的時候,會把每個標簽抽象成代碼里的對象,然后按照這種層次分明的結(jié)構(gòu)組織起來,這就是文檔對象模型,DOM了。畫個圖表示一下就是這樣的:
這就是數(shù)據(jù)結(jié)構(gòu)里典型的「樹」了。所以大家經(jīng)常說DOM樹,其實是一個意思。瀏覽器在解析html的時候,會在它的內(nèi)部構(gòu)建這樣一棵DOM樹,然后按照這棵樹上的層次順序,依次來解析每個標簽。標簽解析完了,用戶就看到了網(wǎng)頁的內(nèi)容。
但是,事情到這里還遠遠沒有結(jié)束,因為還有javascript。瀏覽器解析完了html,然后就要開始解析html里的javascript代碼了。我們知道,程序員可以通過javascript代碼來實現(xiàn)一些動態(tài)的網(wǎng)頁效果,比如去服務器拉取一段數(shù)據(jù)來展示,再比如說做一個酷炫的動畫效果,這些,都還要用到DOM。
舉個簡單的例子,現(xiàn)在javascript想要在網(wǎng)頁里顯示一行字“this is from
javascript”。要做的第一步,就是找到那個可以顯示文字的標簽。這是非常容易的,因為瀏覽器已經(jīng)把DOM都交給javascript了。DOM里的對象,正好就是javascript語言里的對象。于是,通過下面的方法,javascript可以修改DOM樹上的標簽對象。
隨著前端知識的深入,你會發(fā)現(xiàn)javascript操縱DOM是非常普遍事情。比如很多網(wǎng)頁,一開始加載出來只是個架子,只有一個loading在轉(zhuǎn)圈,只有等javascript從服務器上請求到真正的數(shù)據(jù)之后,操縱DOM來顯示數(shù)據(jù),才能看到內(nèi)容,這就是典型的異步加載。再比如html5的游戲,里面的人物要隨著手勢或鼠標來運動,多半也是javascript操縱DOM改變元素的位置來實現(xiàn)的??梢哉f,有了DOM,才使得javascript在前端世界里幾乎無所不能。
但是,有一點要注意,就是操縱DOM本身是一件效率非常低的事情。因為一個網(wǎng)頁往往是很復雜的,瀏覽器構(gòu)造出來的DOM樹往往也是很龐大的,有的甚至有幾千個節(jié)點。在這樣龐大的一棵樹上,進行頻繁的改動,對瀏覽器尤其是移動瀏覽器來說是一個不小的工作量,稍一不注意就卡了。
有人就發(fā)明了一種便捷的方法,叫虛擬DOM。簡單來說就是用javascript又模擬了一棵簡單的DOM樹,然后所有的DOM操作都在這上面演練,這個效率是很高的。等時機成熟的時候,再把虛擬DOM樹和真正的瀏覽器的DOM樹做對比,算出差異,一次性的去改變真正的DOM樹,這個效率也很高。經(jīng)過這兩個步驟,從整體上大大提高了javascript操縱DOM樹的效率。