JavaScript之DOM(下)

Posted 橘猫吃不胖~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript之DOM(下)相关的知识,希望对你有一定的参考价值。

1 事件进阶

1.1 事件概述

事件:用户进行的某种操作
事件源:触发事件的对象
事件处理程序(函数):当事件被触发后所执行的操作(代码)
事件的注册:让浏览器对象能够识别事件

1.2 注册事件

在JavaScript中,注册事件(绑定事件)有两种方式,即传统方式注册事件和事件监听方式注册事件。下面分别针对这两种方式进行讲解。


1、传统方式

元素对象.事件 = function () 

注意:该方式注册事件的特点在于注册事件的唯一性,即同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数。

示例:点击按钮,注册click事件,在控制台输出相应的字

    <button>传统方式注册事件</button>
    <script>
        var btn = document.querySelector("button");
        btn.onclick = function () 
            console.log("用传统方式注册事件");
        
    </script>


2、事件监听方式

由于不同浏览器采用的事件流实现方式不同,事件监听的实现存在兼容性问题。通常根据浏览器的内核,可以把浏览器划分为两大类,一类是早期版本的IE浏览器(如IE 6~IE 8),一类是遵循W3C标准的浏览器(以下简称标准浏览器)。

早期IE内核的浏览器,事件监听方式如下:

DOM对象.attachEvent(type, callback);

type:DOM对象绑定的事件类型,如onclick
callback:事件的处理程序

标准浏览器,包括IE8版本以上的IE浏览器,以及新版的Firefox、Chrome等浏览器,事件监听方式如下:

DOM对象.addEventListener(type, callback, [capture]);

type:DOM对象绑定的事件类型,如click
callback:事件的处理程序
[capture]:默认为false,表示冒泡阶段完成事件处理,true为捕获阶段完成事件处理

注意:该方式注册事件的特点在于可以给同一个DOM对象的同一个事件添加多个事件处理程序

示例:点击按钮,在控制台输出相应的文字

    <button>标准方式注册事件</button>
    <script>
        var btn = document.querySelector("button");
        btn.addEventListener("click", function () 
            console.log("标准方式注册事件");
        , false);
    </script>

1.3 删除事件

事件监听的移除也需要考虑兼容性问题,示例代码如下。

DOM对象.事件名 = null;// 传统方式删除事件
DOM对象.detachEvent(type, callback);// 早期版本IE浏览器
DOM对象.removeEventListener(type, callback);// 标准浏览器

示例:点击两个按钮分别按照传统方式和标准方式注册两个事件,再点击删除按钮删掉两个事件

    <button id="btn1">传统方式注册事件</button>
    <button id="btn2">标准方式注册事件</button>
    <button id="btn3">删除事件</button>
    <script>
        var btn1 = document.querySelector("#btn1");
        btn1.onclick = function () 
            console.log("传统方式注册事件");
        
        var btn2 = document.querySelector("#btn2");
        function test() 
            console.log("标准方式注册");
        
        btn2.addEventListener("click", test, false);
        var btn3 = document.querySelector("#btn3");
        btn3.addEventListener("click", function () 
            btn1.onclick = null;//传统方式删除事件
            btn2.removeEventListener("click", test, false);//标准方式删除事件
        )
    </script>


上面的例子中,先点击“传统方式注册事件”和“标准方式注册事件”两个按钮,控制台分别输出两句话,最后当点击“删除事件”按钮时,再点击“传统方式注册事件”和“标准方式注册事件”两个按钮,控制台将不会输出这两句话,表示事件已被删除。

1.4 DOM事件流

事件流是指当事件发生时,会在发生事件的元素节点与DOM树根节点之间按照特定的顺序进行传播,这个过程称之为事件流。

网景(Netscape)公司团队的事件流采用事件捕获方式,而微软(Microsoft)公司的事件流采用事件冒泡方式,W3C对网景公司和微软公司提出的方案进行了中和处理,规定了事件发生后,首先实现事件捕获,但不会对事件进行处理;然后进行到目标阶段,执行当前元素对象的事件处理程序,但它会被看成是冒泡阶段的一部分;最后实现事件的冒泡,逐级对事件进行处理。

W3C规定的事件流的具体过程对比如下图所示:

2 事件对象

2.1 什么是事件对象

事件对象是一个对象,封装了与事件有关的所有数据,只有当事件发生时才存在,由系统自动创建,是事件处理程序(函数)的默认参数,不需要传递参数。

2.2 事件对象的使用

在标准浏览器中会将一个event对象直接传入到事件处理程序中,而早期版本的IE浏览器(IE 6~IE 8)中,仅能通过window.event才能获取事件对象。

语法结构:

var 事件对象 = window.event;// 早期IE内核浏览器
DOM对象.事件 = function (event) ;// W3C内核浏览器

注意:因为在事件触发时就会产生事件对象,并且系统会以实参的形式传给事件处理函数。所以,在事件处理函数中需要用一个形参来接收事件对象event

示例:点击按钮在控制台输出事件对象

    <button id="btn1">点击按钮输出事件对象</button>
    <script>
        var btn1 = document.querySelector("#btn1");
        btn1.addEventListener("click", function (e) 
            var event = e || window.event;//实现了浏览器的兼容
            console.log("事件对象:", event);
        )
    </script>

2.3 事件对象的常见属性和方法

在事件发生后,事件对象event中会包含一些所有事件都有的属性和方法。所有事件基本上都包括的常用的属性和方法如下表所示。

属性说明浏览器
e.target返回触发事件的对象(事件源)标准浏览器
e.srcElement返回触发事件的对象非标准IE 6-IE 8使用
e.type返回事件的类型所有浏览器
e.stopPropagation()阻止事件冒泡标准浏览器
e.cancelBubble阻止事件冒泡非标准IE 6-IE 8使用
e.preventDefault()阻止默认事件(默认行为)标准浏览器
e.returnValue阻止默认事件(默认行为)非标准IE 6-IE 8使用

表中的type属性是标准浏览器和早期版本IE浏览器的事件对象的公有属性,通过该属性可以获取发生事件的类型,如click、mouseover等(不带on)。


e.target和this的区别:
在事件处理函数中,e.target返回的是触发事件的对象(事件源),而this返回的是绑定事件的对象。示例代码如下:

示例:点击按钮返回触发事件的对象(事件源)和this

    <button id="btn">点击触发事件</button>
    <script>
        var btn = document.querySelector("#btn");
        btn.addEventListener("click", function (e) 
            console.log("触发事件的对象为:", e.target);
            console.log("This:", this);
        )
    </script>


示例:点击按钮返回事件的类型

    <button id="btn">点击触发事件</button>
    <script>
        var btn = document.querySelector("#btn");
        btn.addEventListener("click", function (e) 
            console.log("事件的类型:", e.type);
        )
    </script>


示例:阻止事件冒泡

可以利用事件对象调用stopPropagation()方法和设置cancelBubble属性,实现禁止所有浏览器的事件冒泡行为。

if (window.event) // 早期版本的浏览器
    window.event.cancelBubble = true;
 else // 标准浏览器
    e.stopPropagation();


示例:点击按钮阻止默认事件,阻止点击a标签自动跳转页面

在实际开发中,为了使程序更加严谨,想要确定含有默认行为的标签符合要求后,才能执行默认行为时,可利用事件对象的preventDefault()方法和returnValue属性,禁止所有浏览器执行元素的默认行为。需要注意的是,只有事件对象的cancelable属性设置为true,才可以使用preventDefault()方法取消其默认行为。

    <a href="https://www.baidu.com">跳转到百度</a>
    <script>
        var a = document.querySelector("a");
        a.addEventListener("click", function (e) 
            e.preventDefault();//阻止默认事件,阻止a标签自动跳转
        )
    </script>


效果为点击a标签没有任何反应

2.4 事件委托

原理:不给每个子节点单独设置事件监听器,而是把事件监听器设置在其父节点上,让其利用事件冒泡的原理影响到每个子节点。

简而言之,就是不给子元素注册事件,给父元素注册事件,让处理代码在父元素的事件中执行

这样做的的优点在于,只操作了一次DOM ,提高了程序的性能。

示例:为ul注册事件,点击li之后该li背景色变为粉色

    <ul>
        <li>第1个</li>
        <li>第2个</li>
        <li>第3个</li>
        <li>第4个</li>
    </ul>
    <script>
        var ul = document.querySelector("ul");
        ul.addEventListener("click", function (e) //为父元素注册事件
            e.target.style.backgroundColor = "pink";//背景色变为粉色
            console.log(e.target);
        )
    </script>

3 鼠标事件

3.1 鼠标事件的常用方法

鼠标是计算机的一种输入设备,也是计算机显示系统纵横坐标定位的指示器,所以鼠标事件是Web开发中最常用的一类事件。常见的鼠标事件如下表所示:

事件名称事件触发时机
click单击鼠标左键时触发
focus获得鼠标指针焦点触发
blur失去鼠标指针焦点触发
mouseover鼠标指针经过时触发
mouseout鼠标指针离开时触发
mousedown当按下任意鼠标按键时触发
mouseup当释放任意鼠标按键时触发
mousemove在元素内当鼠标指针移动时持续触发

示例:禁止鼠标右击菜单

contextmenu主要控制应该何时显示上下文菜单,主要应用于程序员取消默认的上下文菜单,示例代码如下:

document.addEventListener('contextmenu', function (e) 
    e.preventDefault();
)

示例:禁止鼠标选中

selectstart事件是鼠标开始选择文字时就会触发,如果禁止鼠标选中,需要禁止该事件的默认行为,示例代码如下:

document.addEventListener('selectstart', function (e) 
    e.preventDefault();
)

3.2 鼠标事件对象

鼠标事件对象MouseEvent,是跟鼠标事件相关的一系列信息的集合,可以用来获取当前鼠标的位置信息,鼠标事件位置属性如下表所示。

位置属性描述
clientX鼠标指针位于浏览器页面当前窗口可视区的水平坐标(X轴坐标)
clientY鼠标指针位于浏览器页面当前窗口可视区的垂直坐标(Y轴坐标)
pageX鼠标指针位于文档的水平坐标(X轴坐标),IE 6~IE 8不兼容
pageY鼠标指针位于文档的垂直坐标(Y轴坐标),IE 6~IE 8不兼容
screenX鼠标指针位于屏幕的水平坐标(X轴坐标)
screenY鼠标指针位于屏幕的垂直坐标(Y轴坐标)

IE 6 ~ IE 8浏览器中不兼容pageX和pageY属性,在项目开发时需要对IE 6~IE 8浏览器进行兼容处理,示例代码如下所示:

var pageX = event.pageX || event.clientX + (document.body.scrollLeft || document.documentElement.scrollLeft)
var pageY = event.pageY || event.clientY + (document.body.scrollTop || document.documentElement.scrollTop)

示例:鼠标移动时鼠标旁边显示鼠标在页面中的的位置(不考虑兼容性)

需要使用鼠标指针移动事件mousemove,每次鼠标移动,都会获得最新的鼠标指针坐标,把这个x和y坐标作为位置的top和left 值就可以实现。

代码如下:

    <style>
        /* 为span标签设置初始的位置 */
        span 
            position: absolute;
            top: 2px;
        
    </style>
    <!-- 将坐标值放在span标签中 -->
    <span></span>
    <script>
        //1、获取元素
        var span = document.querySelector("span");
        //2、给文档注册mousemove(鼠标移动)事件
        document.addEventListener("mousemove", function (e) 
            //获取鼠标在页面中的位置
            var x = e.pageX;
            var y = e.pageY;
            //将鼠标的位置x和y设定给span标签
            span.style.left = x + 10 + "px";//到左边的距离
            span.style.top = y + 10 + "px";//到上边的距离
            //将鼠标的距离显示在div中
            var str = "(" + x + "," + y + ")";
            span.innerhtml = str;
        )
    </script>


效果如上,但是鼠标在截图中无法显示。

4 键盘事件

4.1 键盘事件的常用方法

键盘事件是指用户在使用键盘时触发的事件。例如,用户按Esc键关闭打开的状态栏,按Enter键直接完成光标的上下切换等。常用的键盘事件如下表所示。

事件名称事件触发时机
keypress某个键盘按键被按下时触发,不识别功能键,如Ctrl、Shift、箭头等
保存的是按键的ASCII码值,区分字母大小写
keydown某个键盘按键被按下时触发
保存的是按键的虚拟键码,不区分字母大小写
keyup某个键盘按键被松开时触发
保存的是按键的虚拟键码,不区分字母的大小写

4.2 键盘事件对象

键盘事件对象KeyBoardEvent,是跟键盘事件相关的一系列信息的集合,根据键盘事件对象中的keyCode属性可以得到相应的ASCII码值,进而可以判断用户按下了哪个键。


示例:keypress

    <script>
        document.addEventListener("keypress", function (e) //添加keypress事件
            console.log(e.keyCode);//输出ASCII码值
            console.log(e);//输出事件对象
        )
    </script>

按下键盘上的a后,结果是:

按下键盘上的A后,结果是:

可以看出,keypress区分字母大小写,而且按下shift等功能键之后没有反应。keyCode输出了字母的ASCII码值。


示例:keydown

    <script>
        document.addEventListener("keydown", function (e) //添加keydown事件
            console.log(e.keyCode);
            console.log(e);
        )
    </script>

按下A后,输出结果:

按下a后,输出结果:

按下shift后,输出结果:

因此keydown不区分字母大小写,可以识别功能键。


示例:keyup

    <script>
        document.addEventListener("keyup", function (e) //添加keyup事件
            console.log(e.keyCode);
            console.log(e);
        )
    </script>

按下a之后结果为:

按下A之后结果为:

按下shift之后结果为:

keyup不区分字母大小写,而且可以识别功能键。


示例:判断用户是否按下了s键,如果按下了s键,就将光标定位到搜索框中。

    搜索:<input type="text">
    <script>
        //1、获取文本框元素
        var input = document.querySelector("input");
        //2、给文档注册keyup事件,keyup:按键松开时触发事件
        document.addEventListener("keyup", function (e) 
            if (e.key == "s") //或者是e.keyCode==83
                input.focus();//将焦点移动到输入框上
            
        )
    </script>

没有按下s键时,页面显示如下:

按下s键时,焦点自动到文本框中:

以上是关于JavaScript之DOM(下)的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript之DOM(下)

DOM探索之基础详解——学习笔记

JavaScript宿主对象之BOM和DOM

JavaScript基础之DOM修改样式

更改页面javascript代码(TamperMonkey)以将键盘笔触发送到父DOM

javascript文档碎片