WebAPIs(二)


事件高级

注册事件

事件监听

addEventListener()事件监听

eventTarget.addEventListener()方法将指定的监听器注册到 eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。

该方法接收三个参数: .

type: 事件类型字符串,比如click、mouseover,注意这里不要带on

listener: 事件处理函数,事件发生时,会调用该监听函数

useCapture:可选参数,是一个布尔值,默认是false。学完DOM事件流后,我们再进一步学习

删除事件(解绑事件)

  1. 传统注册方式

    eventTarget.onclick = null;

  2. 方法监听注册方式

    eventTarget. removeEventListener (type,listener[, useCapture]) ;

    eventTarget .detachEvent (eventNameWithon, callback) ;

案例代码

<div>1</div>
<div>2</div>
<div>3</div>
<script>
    var divs = document.querySelectorAll('div');
    divs[0].onclick = function() {
        alert(11);
        // 1. 传统方式删除事件
        divs[0].onclick = null;
    }
    // 2. removeEventListener 删除事件
    divs[1].addEventListener('click', fn) // 里面的fn 不需要调用加小括号
    function fn() {
        alert(22);
        divs[1].removeEventListener('click', fn);
    }
    // 3. detachEvent
    divs[2].attachEvent('onclick', fn1);
    function fn1() {
        alert(33);
        divs[2].detachEvent('onclick', fn1);
    }
</script>

DOM事件流

事件流描述的是从页面中接收事件的顺序。

事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。

比如:我们给页面中的一个div注册了单击事件,当你单击了div时,也就单击了body,单击了html,单击了document。

DOM 事件流会经历3个阶段:

  1. 捕获阶段

  2. 当前目标阶段

  3. 冒泡阶段

注意

  1. Js代码中只能执行捕获或者冒泡其中的一个阶段。

  2. onclick和attachEvent只能得到冒泡阶段。

  3. addEventListener (type, listener[, useCapture])第3三个参数如果是true,表示在事件捕获阶段调用事件处理程序;如果是false (不写默认就是false),表示在事件冒泡阶段调用事件处理程序。

  4. 实际开发中我们很少使用事件捕获,我们更关注事件冒泡。

  5. 有些事件是没有冒泡的,比如Onblur、on Focus、onmouseenter、onmouseleave .

  6. 事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件,我们后面讲解。

事件对象

事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象。

比如:

  1. 谁绑定了这个事件。

  2. 鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置。

  3. 键盘触发事件的话,会得到键盘的相关信息,如按了哪个键。

事件对象的使用

事件触发发生时就会产生事件对象,并且系统会以实参的形式传给事件处理函数。

所以,在事件处理函数中声明1个形参用来接收事件对象。

eventTarget.onclick = function(event) {
//这个event 就是事件对象,我们还喜欢的写成e或者evt
eventTar get .addEventListener( 'click', function(event){
//这个event 就是事件对象,我们还喜欢的写成e或者evt
})
eventTarget. addEventListener('click', fn)
function (event) {
//这个event 就是事件对象,我们还喜欢的写成e或者evt
}

事件对象的属性和方法

e.target 和 this 的区别
  • this 是事件绑定的元素(绑定这个事件处理函数的元素) 。

  • e.target 是事件触发的元素。

常情况下terget 和 this是一致的,
但有一种情况不同,那就是在事件冒泡时(父子元素有相同事件,单击子元素,父元素的事件处理函数也会被触发执行),
	这时候this指向的是父元素,因为它是绑定事件的元素对象,
	而target指向的是子元素,因为他是触发事件的那个具体元素对象。

阻止默认行为

html中一些标签有默认行为,例如a标签被单击后,默认会进行页面跳转。

案例代码

<a href="http://www.baidu.com">百度</a>
<script>
    // 2. 阻止默认行为 让链接不跳转 
    var a = document.querySelector('a');
    a.addEventListener('click', function(e) {
         e.preventDefault(); //  dom 标准写法
    });
    // 3. 传统的注册方式
    a.onclick = function(e) {
        // 普通浏览器 e.preventDefault();  方法
        e.preventDefault();
        // 我们可以利用return false 也能阻止默认行为 没有兼容性问题
        return false;
    }
</script>

事件委托

把事情委托给别人,代为处理。

事件委托也称为事件代理,在 jQuery 里面称为事件委派。

说白了就是,不给子元素注册事件,给父元素注册事件,把处理代码在父元素的事件中执行。

生活中的代理:

1551172082624

js事件中的代理:

1551172159273

事件委托的原理

​ 给父元素注册事件,利用事件冒泡,当子元素的事件触发,会冒泡到父元素,然后去控制相应的子元素。

事件委托的作用

  • 我们只操作了一次 DOM ,提高了程序的性能。

  • 动态新创建的子元素,也拥有事件。

案例:获取鼠标在页面的坐标

<script>
    // 鼠标事件对象 MouseEvent
    document.addEventListener('click', function(e) {
        // 1. client 鼠标在可视区的x和y坐标
        console.log(e.clientX);
        console.log(e.clientY);
        console.log('---------------------');
        // 2. page 鼠标在页面文档的x和y坐标
        console.log(e.pageX);
        console.log(e.pageY);
        console.log('---------------------');
        // 3. screen 鼠标在电脑屏幕的x和y坐标
        console.log(e.screenX);
        console.log(e.screenY);
    })
</script>

常用的键盘事件

键盘事件 触发条件
onkeyup 某个键盘按键被松开时触发
onkeydown 某个键盘按键被按下时触发
onkeypress 某个键盘按键被按下时触发但是它不识别功能键 比如ctrl shift箭头等

键盘事件对象

使用keyCode属性判断用户按下哪个键

案例:模拟京东按键输入内容

当我们按下 s 键, 光标就定位到搜索框(文本框获得焦点)

<input type="text">
    <script>
        // 获取输入框
        var search = document.querySelector('input');
		// 给document注册keyup事件
        document.addEventListener('keyup', function(e) {
            // 判断keyCode的值
            if (e.keyCode === 83) {
                // 触发输入框的获得焦点事件
                search.focus();
            }
        })
    </script>

BOM

什么是BOM

BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window。

BOM 由一系列相关的对象构成,并且每个对象都提供了很多方法与属性。

BOM 缺乏标准,JavaScript 语法的标准化组织是 ECMA,DOM 的标准化组织是 W3C,BOM 最初是Netscape 浏览器标准的一部分。

BOM的构成

顶级对象Windows

window对象是浏览器的顶级对象,它具有双重角色。

  1. 它是JS访问浏览器窗口的一个接口。

  2. 它是一个全局对象。定义在全局作用域中的变量、函数都会变成window对象的属性和方法。

在调用的时候可以省略window,前面学习的对话框都属于window对象方法,如alert()、prompt()等。

window对象的常见事件

页面(窗口)加载事件(2种)

window.onload = function() {}
//或者
window. addEventListener ("load", function() {}) ;

window.onload 是窗口 (页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS 文件等), 就调用的处理函数。

  1. 有了window.onload就可以把JS代码写到页面元素的上方,因为onload是等页面内容全部加载完毕,再去执行处理函数。

  2. window.onload传统注册事件方式只能写一-次, 如果有多个,会以最后一个 window.onload为准。

  3. 如果使用addEventListener则没有限制

document . addEventListener (‘ DOMContentLoaded’ , function() {})

DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等。

调整窗口大小事件

window.onresize = function() {}
//或者
window . addEventlistener("resize", function() {}) ;

window.onresize 是调整窗口大小加载事件, 当触发时就调用的处理函数。

注意:

  1. 只要窗口大小发生像素变化,就会触发这个事件。

  2. 我们经常利用这个事件完成响应式布局。 window.innerWidth 当前屏幕的宽度

<script>
    // 注册页面加载事件
    window.addEventListener('load', function() {
        var div = document.querySelector('div');
    	// 注册调整窗口大小事件
        window.addEventListener('resize', function() {
            // window.innerWidth 获取窗口大小
            console.log('变化了');
            if (window.innerWidth <= 800) {
                div.style.display = 'none';
            } else {
                div.style.display = 'block';
            }
        })
    })
</script>
<div></div>

定时器

window 对象给我们提供了 2 个非常好用的方法——定时器。

  • setTimeout()
  • setInterval()

setTimeout() 炸弹定时器

开启定时器

window.setTimeout (调用函数,[ 延迟的毫秒数]) ;

注意

  1. window可以省略。

  2. 这个调用函数可以直接写函数,或者写函数名或者采取字符串‘函数名0‘三 种形式。第三种不推荐

  3. 延迟的毫秒数省略默认是0,如果写,必须是毫秒。

  4. 因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。

setInterval() 闹钟定时器

开启定时器

window.setInterval (回调函数,[间隔的毫秒数]) ;

注意

  1. window可以省略。

  2. 这个调用函数可以直接写函数,或者写函数名或者采取字符串’函数名0’三种形式。

  3. 间隔的毫秒数省略默认是0,如果写,必须是毫秒,表示每隔多少毫秒就自动调用这个函数。

  4. 因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。

  5. 第一-次执行也是间隔毫秒数之后执行,之后每隔毫秒数就执行- -次。

案例:倒计时

案例分析

① 这个倒计时是不断变化的,因此需要定时器来自动变化(setInterval)

②三个黑色盒子里面分别存放时分秒

③三个黑色盒子利用innerHTML放入计算的小时分钟秒数

④第一次执行也是间隔亳秒数,因此刚刷新页面会有空白

⑤最好采取封装函数的方式,这样可以先调用一-次这 个函数,防止刚开始刷新页面有空白问题

<div>
        <span class="hour">1</span>
        <span class="minute">2</span>
        <span class="second">3</span>
    </div>
    <script>
        // 1. 获取元素(时分秒盒子) 
        var hour = document.querySelector('.hour'); // 小时的黑色盒子
        var minute = document.querySelector('.minute'); // 分钟的黑色盒子
        var second = document.querySelector('.second'); // 秒数的黑色盒子
        var inputTime = +new Date('2019-5-1 18:00:00'); // 返回的是用户输入时间总的毫秒数

        countDown(); // 我们先调用一次这个函数,防止第一次刷新页面有空白 

        // 2. 开启定时器
        setInterval(countDown, 1000);
		
        function countDown() {
            var nowTime = +new Date(); // 返回的是当前时间总的毫秒数
            var times = (inputTime - nowTime) / 1000; // times是剩余时间总的秒数 
            var h = parseInt(times / 60 / 60 % 24); //时
            h = h < 10 ? '0' + h : h;
            hour.innerHTML = h; // 把剩余的小时给 小时黑色盒子
            var m = parseInt(times / 60 % 60); // 分
            m = m < 10 ? '0' + m : m;
            minute.innerHTML = m;
            var s = parseInt(times % 60); // 当前的秒
            s = s < 10 ? '0' + s : s;
            second.innerHTML = s;
        }
    </script>

location对象

window对象给我们提供了一个location属性用于获取或设置窗体的URL,并且可以用于解析URL。因为这个属性返回的是一个对象, 所以我们将这个属性也称为location对象。

location 对象的属性

location对象属性 返回值
location.href 获取或者设置整个URL
location. host 返回主机(域名)
location.port 返回端口号如果未写返回空字符串
location.pathname 返回路径
location. search 返回参数

location对象的常见方法

location对象方法 返回值
location.assign() 跟href一样,可以跳转页面(也称为重定向页面)
location.replace() 替换当前页面,因为不记录历史,所以不能后退页面
location.reload() 重新加载页面,相当于刷新按钮或者f5如果参数为true强制刷新ctrl+f5

navigator 对象包含有关浏览器的信息,它有很多属性,我们最常用的是 userAgent,该属性可以返回由客户机发送服务器的 user-agent 头部的值。

history对象

window对象给我们提供了一个 history对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL。

history对象方法 作用
back() 可以后退功能
forward() 前进功能
go(参数) 前进后退功能参数如果是1前进1个页面如果是-1后退1个页面

history对象一般在实际开发中比较少用,但是会在一些 OA 办公系统中见到。

JS执行机制

JS 是单线程

JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。这是因为Javascript这门脚本语言诞生的使命所致一JavaScript 是为处理页面中用户的交互,以及操作DOM而诞生的。比如我们对某个DOM元素进行添加和删除操作,不能同时进行。应该先进行添加,之后再删除。

单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。
这样所导致的问题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

同步任务和异步任务

为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程,但是子线程完全受主线程控制。于是,JS 中出现了同步任务异步任务

同步

前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。

异步

你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。

异步任务

JS的异步是通过回调函数实现的。

一般而言,异步任务有以下三种类型:

1、普通事件,如click、 resize等

2、资源加加载,如load、error等

3、定时器,包括setInterval、 setTimeout等

异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)

JS执行机制(事件循环)

触屏事件

常见的触屏事件:

触屏touch事件 说明
touchstart 手指触摸到一个DOM元素时触发
touchmove 手指在一个DOM元素上滑动时触发
touchend 手指从一个DOM元素上移开时触发

触摸事件对象(TouchEvent)

TouchEvent 是一类描述手指在触摸平面(触摸屏、触摸板等)的状态变化的事件。这类事件用于描述一个或多个触点,使开发者可以检测触点的移动,触点的增加和减少,等等

touchstart、touchmove、touchend 三个事件都会各自有事件对象。

触摸事件对象重点我们看三个常见对象列表:

触摸列表 说明
touches 正在触摸屏幕的所有手指的一个列表
targetTouches 正在触摸当前DOM元素上的手指的一个列表
changedTouches 手指状态发生了改变的列表,从无到有,从有到无变化

移动端拖动元素

  1. touchstart、touchmove、touchend 可以实现拖动元素
  2. 但是拖动元素需要当前手指的坐标值 我们可以使用  targetTouches[0] 里面的pageX 和 pageY
  3. 移动端拖动的原理:    手指移动中,计算出手指移动的距离。然后用盒子原来的位置 + 手指移动的距离
  4. 手指移动的距离:  手指滑动中的位置 减去  手指刚开始触摸的位置

拖动元素三步曲:

(1) 触摸元素 touchstart: 获取手指初始坐标,同时获得盒子原来的位置

(2) 移动手指 touchmove: 计算手指的滑动距离,并且移动盒子

(3) 离开手指 touchend:

classList 属性

classList属性是HTML5新增的一个属性,返回元素的类名。但是ie10以上版本支持。

该属性用于在元素中添加,移除及切换 CSS 类。有以下方法

添加类:

element.classList.add(’类名’);

focus.classList.add('current');

移除类:

element.classList.remove(’类名’);

focus.classList.remove('current');

切换类:

element.classList.toggle(’类名’);

focus.classList.toggle('current');

注意:以上方法里面,所有类名都不带点

本地存储

随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案。

本地存储特性

1、数据存储在用户浏览器中

2、设置、读取方便、甚至页面刷新不丢失数据

3、容量较大,sessionStorage约5M、localStorage约20M

4、只能存储字符串,可以将对象JSON.stringify() 编码后存储

window.sessionStorage

1、生命周期为关闭浏览器窗口

2、在同一个窗口(页面)下数据可以共享

3、以键值对的形式存储使用

存储数据:

sessionStorage.setItem(key, value)

获取数据:

sessionStorage.getItem(key)

删除数据:

sessionStorage.removeItem(key)

清空数据:(所有都清除掉)

sessionStorage.clear()

window.localStorage

1、声明周期永久生效,除非手动删除 否则关闭页面也会存在

2、可以多窗口(页面)共享(同一浏览器可以共享)

3.  以键值对的形式存储使用

存储数据:

localStorage.setItem(key, value)

获取数据:

localStorage.getItem(key)

删除数据:

localStorage.removeItem(key)

清空数据:(所有都清除掉)

localStorage.clear()

案例:记住用户名

<body>
    <input type="text" id="username"> <input type="checkbox" name="" id="remember"> 记住用户名
    <script>
        var username = document.querySelector('#username');
        var remember = document.querySelector('#remember');
        if (localStorage.getItem('username')) {
            username.value = localStorage.getItem('username');
            remember.checked = true;
        }
        remember.addEventListener('change', function() {
            if (this.checked) {
                localStorage.setItem('username', username.value)
            } else {
                localStorage.removeItem('username');
            }
        })
    </script>
</body>

文章作者: 小小星仔
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 小小星仔 !
评论
  目录