JavaScript进阶之路之事件编程详解【内附飞机发子弹源代码】

一、 事件编程概述

1.1 事件驱动及程序

当用户的行为(点击、移动)发生时,会自动被JavaScript引擎中的事件驱动所捕获并执行相应的事件处理程序,
我们把这个过程就称之为
 事件驱动式 

所谓的事件处理程序就是在事件发生时所执行的程序,就称之为 事件的处理程序 

 

1.2 常用事件

1.2.1 页面事件

onload :当页面载入完毕后触发

1.2.2 焦点事件

onfocus :当获得焦点时触发
onblur :当失去焦点时触发

1.2.3 鼠标事件

onmouseover :当鼠标悬浮时触发
onmouseout :当鼠标离开时触发
onmousedown :当鼠标按下时触发
onmouseup :当鼠标弹起时触发
onmousemove :当鼠标移动时触发
onclick : 当单击时触

1.2.4 键盘事件

onkeypress:键被按下后又被释放,输入了字符
onkeydown:当键盘按下时触发
onkeyup :当键盘弹起时触发

1.2.5 form表单事件

onsubmit:当表单提交时触发
onreset :当表单重置时触发(
<input type=’reset’ value=’重置’ />

1.2.6 内容变化事件

onchange: 当内容改变且失去焦点时触发
oninput : 当内容改变时触发

二、 事件绑定

所谓的事件绑定就是对某个对象的某个事件绑定相应的事件处理程序。
前面我们已经用过两个了;
其实,事件的绑定有三种形式:行内绑定、动态绑定、事件监听

2.1 行内绑定

HTML语言允许在元素标签的属性中,直接定义某些事件的监听代码。

2.2 动态绑定

Element节点对象有事件属性,同样可以绑定事件。

 

2.3 事件监听

addEventListener方法用于在当前节点或对象上,定义一个特定事件的监听函数;

// 使用格式

target.addEventListener(type, listener[, useCapture])

addEventListener方法接受三个参数:
type:事件名称,大小写敏感。
listener:监听函数。事件发生时,会调用该监听函数。
useCapture:布尔值,表示监听函数是否在捕获阶段触发(后面事件传播细讲),
默认为false(监听函数只在冒泡阶段被触发)

2.4 三种事件绑定的区别

this关键字
在JavaScript中,每一个函数的内部都存在一个this关键字,其随着运行环境的不同,其指向也是不同的。

 

小总结:

行内绑定:事件处理程序中的this指向 window对象

动态绑定:事件处理程序中的this指向当前对象

动态绑定及行内绑定:为同一个元素绑定相同事件时,会被覆盖;事件监听不会覆盖

总结:
第一种 "HTML标签的on-属性",违反了HTML与JavaScript代码相分离的原则;处理函数中 this 指向的window对象;
第二种 "Element节点的事件属性" 的缺点是,同一元素同一个事件只能定义一个监听函数,也就是说,如果定义两次onclick属性,后一次定义会覆盖前一次。但是处理函数中的 this 指向的选中的对象;
所以,这两种方法都不推荐使用,除非是为了程序的兼容问题,因为所有浏览器都支持这两种方法。
第三种:addEventListener方法可以针对同一个元素的同一个事件,添加多个监听处理函数。
处理函数中的 this 指向的也是选中的元素;

2.5 移除事件监听

 

三、事件的传播

3.1 现象

 

三个包裹着的DIV,都绑定了点击事件,问:
当点击 div1 时,会发生什么现象?

<head>

    <title></title>

    <meta charset="UTF-8">

    <style>

        div{padding: 40px}

        #div3{width: 300px;height: 300px;background-color: red}

        #div2{width: 200px;height: 200px;background-color: yellow}

        #div1{width: 100px;height: 100px;background-color: blue}

    </style>

</head>

<body>

    <div id="div3">3

        <div id="div2">2

            <div id="div1">1</div>

        </div>

    </div>

</body>

<script>

    var d1 = document.getElementById('div1');

    var d2 = document.getElementById('div2');

    var d3 = document.getElementById('div3');

 

    d1.onclick = function(){

        alert('1');

    }

    d2.onclick = function(){

        alert('2');

    }

    d3.onclick = function(){

        alert('3');

    }

</script>

 

当点击div1时,触发 事件1,但是,紧跟着,事件2和事件3也被触发了;

这种现象,我们称为 事件冒泡

在JS中当一个事件发生以后,它会在不同的DOM节点之间传播。
这种传播分成三个阶段:
第一阶段:从window对象传导到目标节点,称为
 捕获阶段
第二阶段:在目标节点上触发,称为 目标阶段
第三阶段:从目标节点传导回window对象,称为 冒泡阶段

 

事件的传播顺序:html->body->div3->div2->div1   :捕获阶段及目标阶段

Div1->div2->div3->body->html:冒泡阶段

3.2 设置事件执行阶段

想让事件监听在捕获阶段,只能通过 addEventListener 方法的进行设置:

动态绑定和行内绑定的事件都是在冒泡阶段执行,且不能改变;

 

四、 事件对象

4.1 事件对象概述

事件发生以后,会生成一个 事件对象,作为参数传给监听函数。
有关事件发生的一切信息,都包含在这个事件对象中
根据事件类型的不同,事件对象中包含的信息也有所不同;
如点击事件中,包含鼠标点击的横纵坐标位置,键盘事件中,包含键盘的键值等;

 

 

4.2 飞机发子弹小游戏

 

4.3 事件对象的常用元素

4.3.1 事件常用属性

event.bubbles:属性返回一个布尔值,表示当前事件是否会冒泡;
event.eventPhase:返回一个整数值,表示事件目前所处的节点

0:事件目前没有发生。
1:事件目前处于捕获阶段。
2:事件到达目标节点。
3:事件处于冒泡阶段。

event.type:返回一个字符串,表示事件类型,大小写敏感;
event.timeStamp:返回一个毫秒时间戳,表示距离用户上一次刷新至该事件触发的时间;

4.3.2 事件代理/委托

event.target:属性返回触发事件的那个节点,即事件最初发生的节点。
event.currentTarget:属性返回事件当前所在的节点,即正在执行的监听函数所绑定的那个节点。
作为比较,target属性返回事件发生的节点。

由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父
节点上,由父节点的监听函数统一处理多个子元素的事件。
这种方法叫做事件的代理也叫事件委托

4.3.3 阻止浏览器默认行为&阻止事件传播

event.preventDefault()
方法取消浏览器对当前事件的默认行为,
比如点击链接后,浏览器跳转到指定页面,或者按一下空格键,页面向下滚动一段距离。

event.stopPropagation()
方法阻止事件在DOM中继续传播,防止再触发定义在别的节点上的监听函数

 

五、DOM模型

5.1 基本概念

DOM是JavaScript操作网页的接口,全称为“文档对象模型”(Document Object Model)。
它的作用是将网页转为一个JavaScript对象,从而可以用脚本进行各种操作(增删改查)。

浏览器会根据DOM模型,将结构化文档(比如HTML和XML)解析成一系列的节点,
再由这些节点组成一个树状结构(DOM Tree)。
所有的节点和最终的树状结构,都有规范的对外接口。

JavaScript是一门编程语言,而DOM是浏览器对HTML文档结构化后的一个模型;
严格地说,DOM不属于JavaScript,但是我们最常用的就是使用JavaScript操作DOM;

 

5.2 节点的概念

DOM的最小组成单位叫做节点(node)。文档的树形结构(DOM树),就是由各种不同类型的节点组成。
每个节点可以看作是文档树的一片叶子。

最顶层的节点就是document节点,它代表了整个文档。是文档的根节点,
每张网页都有自己的document节点,window.document属性就指向这个节点,
只要浏览器开始载入HTML文档,这个节点对象就存在了,可以直接调用。
每一个HTML标签元素,在DOM树上都会转化成一个Element节点对象;
文档里面最高一层一般是HTML标签,其他HTML标签节点都是它的下级。

除了根节点以外,其他节点对于周围的节点都存在三种关系:

父节点关系(parentNode):直接的那个上级节点

子节点关系(childNodes):直接的下级节点

同级节点关系(sibling):拥有同一个父节点的节点

5.3 查找节点

上一节我们知道,整个文档的节点就是document节点,那么想要具体找到某个节点,
我们可以使用document提供的一系列方法:

getElementsByTagName()
返回所有指定HTML标签的元素,返回值是一个类似数组的HTMLCollection对象;匹配失败,返回[]
参数是想要获取节点的具体节点名称,就是 标签名;

getElementsByClassName()
返回所有class名字符合指定条件的元素,返回值是一个类似数组的HTMLCollection对象;匹配失败,返回[]
参数为 标签的class属性的值

getElementsByClassName()
返回所有class名字符合指定条件的元素,返回值是一个类似数组的HTMLCollection对象;匹配失败,返回[]
参数为 标签的class属性的值

getElementById()
返回匹配指定id属性的元素节点;没有发现匹配的节点,则返回null
参数为 标签的id属性的值,参数大小写敏感;

querySelector()、querySelectorAll()
document.querySelector方法接受一个CSS选择器作为参数,返回匹配该选择器的元素节点;
如果有多个节点满足匹配条件,则返回第一个匹配的节点。如果没有发现匹配的节点,则返回null;

document.querySelectorAll方法与querySelector用法类似
区别是返回一个类似数组的HTMLCollection对象,包含所有匹配给定选择器的节点。

但是,它们不支持CSS伪元素的选择器(比如:first-line和:first-letter)
和伪类的选择器(比如:link和:visited),即无法选中伪元素和伪类。

 

5.4 创建节点及添加节点

创建节点,也需要使用document提供的一些列方法;

createElement()
用来生成网页元素节点,参数为元素的标签名;

createTextNode()
用来生成文本节点,参数为所要生成的文本节点的内容;

appendChild()
接受一个节点对象作为参数,将其作为最后一个子节点,插入当前节点;

hasChildNodes()
返回一个布尔值,表示当前节点是否有子节点
removeChild()
接受一个子节点作为参数,用于从当前节点移除该子节点

cloneNode()
用于克隆一个选中的节点。
它接受一个布尔值作为参数,表示是否同时克隆子节点,默认是false,即不克隆子节点。
注意:
 不会克隆绑定到该元素上的事件;

innerHTML
返回该元素包含的 HTML 代码。该属性可读写,常用来设置某个节点的内容;

5.5 节点属性

HTML元素节点的标准属性(即在标准中定义的属性),会自动成为元素节点对象的属性

属性操作的标准方法

getAttribute()
返回当前元素节点的指定属性。如果指定属性不存在,则返回null;

setAttribute()
为当前元素节点新增属性。如果同名属性已存在

hasAttribute()
返回一个布尔值,表示当前元素节点是否包含指定属性

removeAttribute()
从当前元素节点移除属性

5.6 关系节点

nextElementSibling
返回紧跟在当前节点后面的第一个同级Element节点,如果当前节点后面没有同级节点,则返回null;
previousElementSibling
返回紧跟在当前节点前面的第一个同级Element节点,如果当前节点前面没有同级节点,则返回null;
parentElement
返回当前节点的父级Element节点;
childNodes
返回一个NodeList集合,成员包括当前节点的所有子节点(注意空格回车也算)。

 

5.7 CSS操作

每个DOM对象都有style属性,我们可以直接操作,用来读写行内CSS样式
之前,我们已经简单的使用过JS控制元素的CSS样式;
在具体使用的时候还有一些需要重点注意的细节:
名字需要改写,将横杠从CSS属性名中去除,然后将横杠后的第一个字母大写:
比如background-color写成backgroundColor
属性值都是字符串,设置时必须包括单位:
比如,divStyle.width的值不能写为100,而要写为100px

如果将 样式表写在 style 标签内,某些属性是无法获取的,如宽高;
行内样式(inline style)具有最高的优先级,改变行内样式,通常会立即反映出来。
但是,网页元素最终的样式是综合各种规则计算出来的。
因此,如果想得到元素现有的样式,只读取行内样式是不够的,我们需要得到浏览器最终计算出来的那个样式规则。

getComputedStyle()
接受一个节点对象,返回该节点对象最终样式信息的对象,所谓“最终样式信息”,指的是各种CSS规则叠加后的结果。

我是小咖

发个邀请:
如果你正好想学习php,可以与我一起交流,我的VX:feilueze333。下面资料免费赠送

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值