DOM中的各類區別小節

相信你們在DOM的實際開發與學習過程當中,確定也遇到很多須要比較的東西,這裏我主要列比較如下幾點,更多的區別和總結,但願想到和遇到的朋友給我留言哦。javascript

  • clientHeight/scrollHeight/offsetHeight
  • defer vs async
  • 事件模型-捕獲/目標/冒泡
  • 普通事件 vs 事件綁定
  • stopPropagation/preventDefault/return false
  • target/currentTarget

文中示例顯示不是很好,能夠直接去小弟博客看原文:DOM中的各類區別小節css

各類height/width

CSS盒模型是比較複雜的,尤爲是當頁面中有滾動條時,僅僅經過css來操做高度寬度是不夠的,幸運的是Javascript提供了很多這樣的接口。Javascript中clientHeight / cliengWidthscrollHeight / scrollWidthoffsetHeight / offsetWidthheight / width 均可以獲取高度和寬度,可是他們有一些細微的差異:html

See the Pen 各類height/width區別 by superlin (@superlin) on CodePen.java

<script async src="//assets.codepen.io/assets/embed/ei.js"></script>
  • offsetHeight / offsetWidth:可見區域包含border,對於display:block的元素經過width/height + padding + border能夠計算出來。
  • clientHeight / cliengWidth:可見區域包含padding,不包含border和滾動條,不能經過CSS樣式計算出來,取決於滾動條的大小。
  • scrollHeight / scrollWidth:內容區域的大小,不包含border,包含不在可見區域內的隱藏部分,不能經過CSS樣式計算出來。
  • height / width:不包含borderpadding

另外:滾動條的寬度能夠經過以下方式計算:web

javascriptscrollbarWidth = offsetWidth - clientWidth - getComputedStyle().borderLeftWidth - getComputedStyle().borderRightWidth

defer與async

<script>標籤的deferasync屬性大多數瀏覽器都已經支持了(IE9如下不支持defer),那麼他們到底有什麼區別呢?這裏咱們用幾張圖來描述,相信看完以後你就很清楚他們的區別了,首先對於圖示作以下說明:segmentfault

legend

<script>:若是script不帶任何屬性,這種狀況下HTML文檔遇到js腳本就會停止解析,先發送請求下載文件,下載完成後執行腳本,以後再繼續解析HTML文檔。瀏覽器

script

<script async>:帶有async屬性時,js腳本下載不會使HTML文檔解析停止,下載完成後纔會停止文檔解析,執行完成後再繼續解析文檔。dom

async

<script defer>:帶有defer屬性時,js腳本下載不會使HTML文檔解析停止,並且js執行都是在文檔解析完成以後。async

defer

通常狀況下,能用async就用async,而後是defer,最後纔是什麼屬性都不帶,主要的規則以下:模塊化

  • 若是當前腳本是模塊化的,並且不依賴其餘腳本,使用async
  • 若是當前腳本依賴於其餘腳本或被其餘腳本所依賴,使用defer
  • 若是腳本文件很小,並且被其餘async腳本依賴,能夠將當前腳本做爲內聯腳本放在那些async腳本的前面

事件捕獲與冒泡

先來看一個簡單的問題,假設有一個element1元素,裏面還有一個element2元素。

-----------------------------------
| element1                        |
|   -------------------------     |
|   |element2               |     |
|   -------------------------     |
|                                 |
-----------------------------------

這兩個元素都綁定了click事件,若是用戶點擊element2,那個先觸發呢,換句話說事件觸發的的順序是怎樣的呢?

  • 網景公司說element1優先,這叫事件捕獲(event capturing)
  • 微軟則堅持element2優先,這叫事件冒泡(event bubbling)

首先來看看事件捕獲:

| |
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  \ /          |     |
|   -------------------------     |
|        Event CAPTURING          |
-----------------------------------

能夠看出element1上的事件處理函數先觸發,element2上的事件處理函數後觸發。

那麼事件冒泡又是怎樣的呢:

/ \
 ---------------| |-----------------
 | element1     | |                |
 |   -----------| |-----------     |
 |   |element2  | |          |     |
 |   -------------------------     |
 |        Event BUBBLING           |
 -----------------------------------

這種狀況下element2上面的事件處理函數先觸發,element1上面的事件處理函數後觸發。

對於這兩種模型的大相徑庭,W3C很巧妙地在這場對抗中保持中立:任何W3C事件模型中發生的事件都是先捕獲,直到它到達目標元素,而後再向外冒泡

| |  / \
-----------------| |--| |-----------------
| element1       | |  | |                |
|   -------------| |--| |-----------     |
|   |element2    \ /  | |          |     |
|   --------------------------------     |
|        W3C event model                 |
------------------------------------------

基於事件模型能夠有不少應用,最多見的就是事件代理和委託,感興趣的能夠深刻研究,這裏我不在具體描述。

普通事件與事件綁定

普通事件就是on+event綁定的事件,Javascript中有不少定義好的事件,例如 onclickonkeyuponmouseup 等,這種方式的使用示例以下:

javascriptobj1.onclick = function1;
obj1.onclick = function2;

以上的操做下,function1會被function2覆蓋而只執行function2,解除事件只需:

javascriptobj1.onclick = null;

使用支持W3C標準的瀏覽器中綁定事件用的是addEventListener:

javascriptobj1.addEventListener("click",change1,false);
obj1.addEventListener("click",change2,false);

事件執行順序跟綁定順序同樣,先執行change1,再執行change2,解除綁定:

javascriptobj1.removeEventListener("click",change1,false);

在IE裏面,綁定事件要用attachEvent:

javascriptobj1.attachEvent("onclick",change1);
obj1.attachEvent("onclick",change2);

綁定時事件名稱一樣要以on爲前綴,並且沒有後面是否冒泡的boolean值,可是這種執行順序變成了倒序,先執行change2,再執行change1。 事件取消綁定:

javascriptobj1.detachEvent("onclick",change1);

stopPropagation,preventDefault和return false

由於有父, 子節點同在, 由於有監聽事件和瀏覽器默認動做之分. 使用 JavaScript 時爲了達到預期效果常常須要阻止事件和動做執行. 通常咱們會用到三種方法, 分別是 stopPropagation(), preventDefault()return false。那麼他們有什麼區別呢?

See the Pen stopPropagation,preventDefault和return false對比 by superlin (@superlin) on CodePen.

<script async src="//assets.codepen.io/assets/embed/ei.js"></script>

stopPropagation:由於事件能夠在各層級的節點中傳遞, 不論是冒泡仍是捕獲, 有時咱們但願事件在特定節點執行完以後再也不傳遞, 可使用事件對象的 stopPropagation 方法。

preventDefault:元素上帶有的功能. 如: 點擊 a 連接節點的跳轉動做, 點擊submit按鈕表單會提交等,若是監聽這些元素的事件時不但願默認動做方式,就可使用 preventDefault 方法。

return false:退出執行, return false 以後的全部觸發事件和動做都不會被執行. 有時候 return false 能夠用來替代 stopPropagationpreventDefault,除此以外,還能夠返回對象, 跳出循環等。

能夠去上面的例子試試哦。

target與currentTarget

target在事件流的目標階段;currentTarget在事件流的捕獲,目標及冒泡階段。只有當事件流處在目標階段的時候,兩個的指向纔是同樣的, 而當處於捕獲和冒泡階段的時候,target指向被單擊的對象而currentTarget指向當前事件活動的對象(通常爲父級),具體示例以下。

See the Pen target與currentTarget區別 by superlin (@superlin) on CodePen.

<script async src="//assets.codepen.io/assets/embed/ei.js"></script>

更多的例子和意見請給我留言。

歡迎光臨小弟博客:Superlin's Blog
個人博客原文:DOM中的各類區別小節

參考

相關文章
相關標籤/搜索