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中的各类区别小节

参考

相关文章
相关标签/搜索