DOM事件模型

  1. DOM level 0
    我们来看看如下代码:

html代码:

<body>
  <button id="X" onclick="print">A</button>
  <button id="Y" onclick="print()">B</button>
  <button id="Z" onclick="print.call()">C</button>
</body>

JS代码:

function print() {
  console.log("hi");
}

X.onclick = print;  // 类型为函数
Y.onclick = print();  //  undefined
Z.onclick = print.call();

大家觉得A,B,C,X,Y和Z哪几个能执行print函数呢?

答案是: B,C,X

在html中的button上的onclick属性里面是「要执行的代码」,onclick="要执行的代码",一旦用户点击,浏览器就eval(“要执行的代码”)。在这里也就是eval("print()").

但是JS中的X.onlick,onclick相当于X的属性,这个属性是一个函数(print)。一旦用户点击,那么浏览器就执行X.onclick.call(x, {});

  1. DOM level 2
    html代码:
<button id="xxx">click</button>

JS代码:

xxx.addEventListener("click", function() { console.log("hi"); });

xxx.onclick = function() { console.log("hi"); });

那这么写与DOM level 0 有啥区别呢?

xxx.onclick是对属性的操作,这个属性唯一,如果想要有两个以上的onclick事件,就不行了。

xxx.onclick = function() {
  console.log(2);
}

xxx.onclick = function() {
  console.log(3);
}

在上述代码中,下面的onclick就会覆盖上面的onclick。

而addEventListener这个模型是一个队列(xxx拥有一个队列 eventListeners)。

接下来我们再说说,事件的「捕捉」和「冒泡」。
html代码:

  <div id="grand">
        爷爷
        <div id="father">
            爸爸
            <div id="son">
                儿子
            </div>
        </div>
    </div>

JS代码:

grand.addEventListener("click", function() {
    console.log("爷爷");
}, false);

father.addEventListener("click", function() {
    console.log("爸爸");
}, false);

son.addEventListener("click", function() {
    console.log("儿子");
}, false);

通过一定的CSS修饰,在页面上面是如下效果:


image.png

那么点击儿子的时候,会点击到爸爸和爷爷吗?

image.png

如图所示,会触发爸爸和爷爷的监听事件。

这种从里面的div往外层div的监听事件就是「事件冒泡」。从外层向里层的监听事件就是「事件捕捉」。

如果执行「事件捕捉」?

grand.addEventListener("click", function() {
    console.log("爷爷");
}, true);

father.addEventListener("click", function() {
    console.log("爸爸");
}, true);

son.addEventListener("click", function() {
    console.log("儿子");
}, true);

只需要把addEventListener的第三个参数换成true就可以了。


image.png

以下是一个模型图:


image.png

其实是以(1)到(6)的顺序来访问的。(fn1,fn2,fn3分别代表爷爷,爸爸,儿子的输出函数)。
在我们把三个监听事件都设置为false的时候,fn1、fn2、fn3分别在图中(4)(5)(6)的位置,按照访问顺序,固然输出“儿子”,“爸爸”,“爷爷”。

那我们如果单独把爸爸那个监听函数的false改为true呢?

grand.addEventListener("click", function fn1() {
    console.log("爷爷");
}, false);

father.addEventListener("click", function fn2() {
    console.log("爸爸");
}, true);

son.addEventListener("click", function fn3() {
    console.log("儿子");
}, false);

此时,fn2函数会出现在(2)处,而fn1和fn3会出现在(4)和(6)处。按照访问顺序,则会输出“爸爸”,“儿子”, “爷爷”。

那如果只对同一个div监听,既冒泡也捕获呢?


son.addEventListener("click", function() {
    console.log("儿子冒泡");
}, false);

son.addEventListener("click", function() {
    console.log("儿子捕获");
}, true);

这个时候不能按那个访问顺序考虑,其实是哪个先写就哪个先执行。上述代码就先输出“儿子冒泡”,然后输出“儿子捕获”。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,809评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,189评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,290评论 0 359
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,399评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,425评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,116评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,710评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,629评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,155评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,261评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,399评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,068评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,758评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,252评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,381评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,747评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,402评论 2 358

推荐阅读更多精彩内容

  • DOM leave 0: xxx.onclick = function(){ ... } onclick="xxx...
    zzzZink阅读 323评论 0 0
  • 什么是DOM? DOM全称为The Document Object Model,应该理解为是一个规范,定义了HTM...
    夜舞暗澜_3ea2阅读 793评论 1 3
  • html中的事件写法与DOM的区别 html里写事件函数要写调用的: 上面的代码B和C是正确的.原因: 一旦用户点...
    hzl的学习小记阅读 223评论 0 0
  • onclick和addEventListener('click', function() {}) xxx.oncl...
    squall1744阅读 697评论 0 2
  • 文中涉及大量内容来自于PPK的博客 现代前端开发应该要遵守: html展示文档内容,css渲染页面效果,javas...
    江枫阅读 769评论 0 8