WebAPI
1.什么是WebAPI
WebAPI能够让不同的应用程序和系统之间进行数据交互,就像人们通过电话交流一样,让不同的系统之间能够相互理解和协作。Web APIs是JS的应用,大量使用JS语法做交互效果
。
WebAPI
:WebAPI是浏览器提供一套操作浏览器功能和页面元素的API(BOM
和DOM
)。
2.为什么要学习WebAPI
学习WebAPI可以让我们了解如何使用网络接口来访问和处理远程数据,提高Web开发的效率和灵活性,为构建更好的Web应用程序提供技术支持。
在这里我们主要针对浏览器学习常用的API,主要针对浏览器做交互效果。
3.MDN
MDN是Mozilla开发者网络的缩写,是一个提供Web开发文档的网站。MDN的目标是帮助开发者更好地理解和使用Web技术,提高Web开发的质量和效率。
MDN详细API地址: https://developer.mozilla.org/zh-CN/docs/Web/API
一.DOM
1.DOM简介
1.1什么是DOM
文档对象模型
(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。
W3C已经定义好了一系列的DOM接口,通过DOM接口可以改变网页的内容、结构和样式。
1.2DOM树
文档:一个页面就是一个文档,DOM使用document
来表示
元素:页面中的所有标签都是元素,DOM中使用element
来表示
节点:网页中的所有内容都是节点(包括标签
、属性
、文本
、注释
等)
2.DOM获取元素
DOM在我们的实际开发中主要用来操作元素,操作页面元素首先要使用document.
的方式。获取到我们获取页面中的元素可以使用以下几种方式:
- 根据元素ID获取
- 根据标签名获取
- 通过HTML5新增的方法获取
- 特殊元素的获取
示例:
<div class="box" id="time">2023-3-23</div>
1.根据ID名获取
getElementById('id')
var timer = document.getElementById('time');
console.log(timer);
console.log(typeof timer); // object 返回的是一个元素对象
console.dir(timer);
- 通过getElementById(‘id’)的方式获取到id为time的div元素对象
- 可以看到getElementById(‘id’)返回的是一个对象object
- 可以使用console.dir()打印我们返回的元素对象,更好的查看里面的属性和方法
示例:
<ul>
<li>知否知否,应是绿肥红瘦11</li>
<li>知否知否,应是绿肥红瘦22</li>
</ul>
<ol id="ol">
<li>东临碣石,以观沧海1</li>
<li>东临碣石,以观沧海2</li>
</ol>
<div>
<p>只有一个p</p>
</div>
2.根据标签名获取
getElementsByTagName('标签名')
var lis = document.getElementsByTagName('li');
console.log(lis); // [li,li]
console.log(lis[0]); // <li>知否知否,应是绿肥红瘦1</li>
- getElementsByTagName(‘标签名’):获取指定标签名的对象集合(返回的是元素对象集合)
- 获取到的元素对象集合是以
伪数组
的形式进行存储的 - 如果页面中没有这个元素,返回的是一个空的伪数组
[]
- 以上getElementsByTagName(‘li’)表示获取到所有的
li
元素 - 在此基础上我们还可以通过某个元素(父元素)内部获取所有指定标签名的子元素,如我们获取ol中的li:
方式1:
var ol = document.getElementsByTagName('ol');
var lis2 = ol[0].getElementsByTagName('li');
console.log(lis2) // [li li]
- 先获取到父元素
ol
,再通过ol[索引号].getElementsByTagName('li')
ol
必须要有索引才能获取到里面的子元素(因为getElementsByTagName()
返回的是伪数组
形式的)
方式2:
var ol2 = document.getElementById('ol');
var lis3 = ol2.getElementsByTagName('li');
console.log(lis3) // [li,li]
- 给
ol
加上id
,然后父元素通过id
获取(常用)
3.H5新增的方式获取
示例:
<div class="box">盒子1</div>
<div class="box">盒子2</div>
<div id="nav">
<ul>
<li>首页</li>
<li>产品</li>
</ul>
</div>
(1)getElementsByClassName('类名')
var boxs = document.getElementsByClassName('box');
console.log(boxs); // [div.box,div.box]
getElementsByClassName('类名')
:根据类名返回元素对象集合- 以上根据类名(
box
)返回了页面中的所有box
元素
(2)querySelector('选择器')
var firstBox = document.querySelector('.box'); // 类选择器
console.log(firstBox); // [div.box]
querySelector('选择器')
: 根据指定选择器返回第一个元素对象- 以上根据类选择器(
.box
)返回了第一个类名为box
的元素
(3)querySelectorAll('选择器')
var AllBox = document.querySelectorAll('.box');
console.log(AllBox); // [div.box,div.box]
querySelectorAll('选择器')
: 根据指定选择器返回所有元素对象集合- 以上根据类选择器(
.box
)返回了所有类名为box
的元素
4.特殊元素获取
(1)document.body
var bodyElm = document.body;
console.log(bodyElm);
-
document.body
: 获取body元素对象 -
以上返回了页面中的body元素
(2)document.documentElement
var htmlElm = document.documentElement;
console.log(htmlElm);
-
document.documentElement
: 获取html元素对象 -
以上返回了页面中的html元素
3.DOM事件
网页中的每个元素都可以产生某些可以触发JavaScript的事件。当用户与网页交互时,浏览器会自动触发相应的事件,我们可以使用JavaScript代码来监听这些事件,并根据需要执行相应的操作。
常见的DOM事件包括鼠标事件
、键盘事件
、表单事件
、窗口事件
等。
事件的三要素:1.事件源 2.注册事件(绑定事件) 3.事件处理程序
1.常见的鼠标事件
鼠标事件触发条件 | |
---|---|
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
ondblclick | 鼠标双击触发 |
2.执行事件的步骤
<div>666</div>
// 1.获取事件源
var div = document.querySelector('div');
// 2.绑定事件(注册事件)
// div.onclick
// 3.添加事件处理程序
div.onclick = function () {
console.log('我被选中了!');
}
- 以上通过获取事件源(
div
)、注册事件(div.onclick
)、事件处理函数(function()
)这三个步骤,当点击div盒子时,控制台就输出了console.log('我被选中了!')
的代码
4.操作元素
JavaScript的DOM操作可以改变网页内容
、结构
和样式
,我们可以利用DOM操作元素来改变元素里面的内容、属性等。
示例:
<button class="btn">222</button>
1.修改元素内容
1.element.innerText
var btn = document.querySelector('.btn')
btn.onclick = function () {
div.innerText = '666';
}
-
element.innerText
可以修改元素的内容 -
以上当点击了按钮时,
<button>
里的内容修改为了666
2.element.innerHTML
var btn = document.querySelector('.btn')
btn.onclick = function () {
div.innerHTML = '666';
}
element.innerHTML
也可以修改元素内容
innerText和innerHTML(常用)的区别:
相同点:
都能改变元素的内容,都能获取元素里的内容(是可读写的)
不同点:
1.innerText不能识别html标签 非标准,innderHTML能识别html标签W3C标准
2.innerText去除空格、换行,而innerHTML保留空格、换行
示例:
<div></div>
<p>
pan很帅
<span>of course</span>
</p>
var div = document.querySelector('div');
div.innerText = '<strong>今天是</strong>:2023-3-24'; // 字体不会加粗
div.innerHTML = '<strong>今天是</strong>:2023-3-24'; // 字体会加粗
var p = document.querySelector('p');
console.log(p.innerText);
console.log(p.innerHTML);
- 以上使用innerText不会将
<strong>
标签的内容加粗,不能识别html标签,而innerHTML识别html标签 - innerText获取到
<p>
中的文本去除了空格、换行,而innerHTML保留空格、换行
2.修改元素属性
DOM操作可以修改网页中元素的属性,如:src
,href
,id
,alt
,title
等,使用element.属性
的方式对元素进行修改。
示例:
div {
width: 320px;
height: 220px;
}
div img {
width: 100%;
height: 100%;
}
<button id="hg">胡歌</button>
<button id="zly">赵丽颖</button> <br>
<div>
<img src="images/hg.jpg" alt="" title="">
</div>
var hg = document.getElementById('hg');
var zly = document.getElementById('zly');
var img = document.querySelector('img');
hg.onclick = function () {
img.src = 'images/hg.jpg';
img.title = '胡歌';
}
zly.onclick = function () {
img.src = 'images/zly.jpg';
img.title = '赵丽颖';
}
- 以上通过
img.src
,img.title
的方式对img的src属性、title属性进行了修改。当点击了按钮时,就可以实现图片和标题的切换
3.修改表单属性
DOM可以操作表单的属性,如:type
,value
,checked
,selected
,disabled
等。通过element.表单属性
修改表单属性。
示例:
<button>按钮</button>
<input type="text" value="8-8-8">
var btn = document.querySelector('button');
var ipt = document.querySelector('input');
btn.onclick = function () {
ipt.value = '被点击啦';
// btn.disabled = true;
this.disabled = true;
}
-
以上修改表单里的内容使用到了
value
属性 -
使用
disabled
属性可以使某个表单要被禁用,不能再点击 -
使用
this
,this
指向的是事件函数的调用者(btn
)
innerHTML
修改元素的内容只能用于普通盒子例如div,p..
等,而要修改表单元素的内容,使用到的是value
属性。
4.修改样式属性
通过操作DOM,我们可以修改元素的大小
、颜色
、位置
等样式。
修改元素的样式属性有: 1.element.style
(行内样式操作) 2. element.className
(类名样式操作)
示例:
div {
width: 200px;
height: 200px;
background-color: pink;
}
1.element.style
var div = document.querySelector('div');
div.onclick = function () {
this.style.backgroundColor = 'orange';
this.style.width = '300px';
}
- 以上使用element.style的方式修改了元素div的backgroundColor(背景颜色),width(宽度)
- 在js修改style样式操作采用的是驼峰命名法
- js修改style样式操作,产生的是行内样式,权重要比css权重高
2.element.className
<div class="first">文本</div>
var div = document.querySelector('div');
div.onclick = function () {
this.className = 'first change'; // 两个类名
}
-
以上使用了element.className的方式修改样式,是以
修改类名
的方式来修改样式 -
我们可以在css中新定义一个
.change
类名,然后写上新的样式,在js
中使用className
更改元素的类名 -
className
会直接更改元素的类名,会覆盖
原先的类名,如果我们想保留原先类名,可以以多类名
的方式 -
如果样式修改比较多,可以采取
element.className
5.自定义属性操作
当我们要获取或设置元素的属性值时可以有两种方式:
1.element.属性
2.element.getAttribute()
。
element.属性
的方式是用于内置属性,而element.getAttribute()
的方式主要是针对自定义的属性
示例:
<div id="demo" index="1" class="one" remov="00"></div>
1.获取元素的属性值
(1)element.属性
console.log(div.id); // id是内置属性
(2)element.getAttribute('属性')
console.log(div.getAttribute('id'));
console.log(div.getAttribute('index')); // index是自定义属性
2.设置元素的属性值
(1)element.属性 = 值
div.id = 'text';
div.className = 'nav';
(2)element.setAttribute('属性','值')
div.setAttribute('index', 2);
div.setAttribute('class', 'nav2');
(3).删除属性值
removeAttribute('属性')
div.removeAttribute('remov');
6.H5自定义属性
在H5自定义属性中,定义属性我们统一设置成以data-
开头,如data-index
H5新增了获取自定义属性的方式:element.dataset.属性名
或element.dataset['属性名']
示例:
<div getTime="20" data-time="10" data-index="2" data-list-name="pan"></div>
1.获取自定义属性
(1)element.getAttribute('属性名')
(兼容性获取)
var div = document.querySelector('div');
console.log(div.getAttribute('getTime')); // 20
console.log(div.getAttribute('data-time')) // 10
- element.getAttribute(‘属性名’)获取属性时,属性名就是完整的属性名
(2) element.dataset.属性名(H5新增方式获取)
var div = document.querySelector('div');
console.log(div.dataset.time); // 10
console.log(div.dataset['index']); // 2
- 使用dateset只能获得以data开头的属性
dataset是一个集合
,里面存放了所有以data-
开头的自定义属性:
console.log(div.dataset); // {time: '10', index: '2'}
若自定义属性名字过长,有多个-
连接,使用dataset获取要驼峰命名:
console.log(div.dataset.listName); // pan
5.节点操作
1.节点概述
网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用node
表示。
节点至少拥有的三个基本属性:nodeType
(节点类型)、nodeName
(节点名称)、nodeValue
(节点值)。
- 元素节点 nodeTyoe 为1
- 属性节点 nodeTyoe 为2
- 文本节点 nodeTyoe 为=3(文本节点包含文字、空格、换行等)
2.为什么要使用到节点
- 利用DOM提供的方法获取元素(document.getElementById()等) 逻辑性不强、繁琐。
- 利用节点层次关系获取元素(父子兄弟节点获取元素)逻辑性强,但是兼容性稍差,这两种方式都可以获取元素,节点操作更简单
1.父节点操作
示例:
<div class="father">
<span class="son"></span>
</div>
node.node.parentNode
var son = document.querySelector('.son');
console.log(son.parentNode);
-
父节点操作使用node.parentNode方式,得到的是最近的父级元素
-
son.parentNode表示获取到父元素节点
-
如果找不到父节点就返回null
2.子节点操作
示例:
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
1.获取子节点
(1) parentNode.childNodes()
var ul = document.querySelector('ul');
console.log(ul.childNodes)
- ul.childNodes()表示ul获取到所有的子节点(包括元素节点、文本节点等)
(2) parentNode.children()
var ul = document.querySelector('ul');
console.log(ul.childNodes)
- ul.children()ul表示获取所有子节点(得到的是元素节点)
常用的是parentNode.children()获取子节点,因为一般我们主要是对元素节点进行操作。
2.获取第一个子元素节点和最后一个子元素节点
(1) parentNode.firstChild
parentNode.lastChild
var ul = document.querySelector('ul');
console.log(ul.firstChild);
console.log(ul.lastChild);
- ul.firstChild,ul.lastChild表示ul获取到第一个/最后一个节点(包含了文本节点、元素节点等)
(2) parentNode.firstElementChild
parentNode.lastElementChild
var ul = document.querySelector('ul');
console.log(ul.firstElementChild);
console.log(ul.lastElementChild);
- ul.firstElementChild,ul.lastElementChild表示获取到第一个/最后一个的子元素节点(但是有兼容性问题,要使用-ie9以上版本浏览器)
(3)parentNode.childen[]
var ul = document.querySelector('ul');
console.log(ul.children[0]);
console.log(ul.children[ul.children.length - 1]);
- ul.children[0]表示ul元素获取第一个子节点(元素节点)
- ul.children[ul.children.length - 1]表示ul元素获取最后一个子节点(元素节点)
3.兄弟节点操作
示例:
<div>我是div</div>
<span>我是span</span>
1.获取兄弟节点
(1) node.nextSibling
node.previousSibling
var div = document.querySelector('div');
console.log(div.nextSibling); // #text
console.log(div.previousSibling); // #text
- div.nextSibling,div.previousSibling表示div元素获取上/下一个兄弟节点(包含文本节点等…)
(2) node.nextElementSibling
node.previousElementSibling
var div = document.querySelector('div');
console.log(div.nextElementSibling);
console.log(div.previousElementSibling)
- div.nextElementSibling div.previousElementSibling表示div获取上/下一个兄弟节点(得到的是元素节点)
- 但是容易有兼容性问题,-ie9以上才支持
解决方式: 自己封装一个兼容性函数
如
function getNextElementSibling(element) {
var el = element;
while (el = el.nextSibling) {
if (el.nodeType === 1) { // 表示得到的是元素节点
return el;
}
}
return null;
}
function getPreviousElementSibling(element) {
var el = element;
while (el = el.previousSibling) { // 表示得到的是元素节点
if (el.nodeType === 1) {
return el;
}
}
return null;
}
4.创建和添加节点
页面中想要添加一个元素,需要: 1.创建节点
2.添加节点
示例:
<ul>
<li>123</li>
</ul>
(1) 创建节点
document.createElement('标签名')
var list = document.createElement('li');
- document.createElement(‘li’)创建了一个li节点(元素)
(2)添加节点
node.appendChild(child)
var ul = document.querySelector('ul');
ul.appendChild(list);
- ul.appendChild(list)表示在后面追加list节点
node.insertBefore(child,指定元素)
ul.insertBefore(list2, ul.children[0]);
- ul.insertBefore(list2, ul.children[0])表示在第一个孩子节点前添加节点
5.删除和克隆节点
(1)删除节点
node.removeChild(child)
ul.removeChild(ul.children[0]);
- ul.removeChild(ul.children[0])表示ul删除第一个子节点(元素节点)
(2)克隆节点
node.cloneNode()
浅拷贝
var list = ul.children[0].cloneNode();
- ul.children[0].cloneNode()表示ul拷贝第一个子节点(浅拷贝)
- node.cloneNode()参数为空或为false时,表示浅拷贝
- 浅拷贝只复制标签本身,不复制内容(内容所有包括子节点等等)
node.cloneNode(true)
深拷贝
var list = ul.children[0].cloneNode(true);
- ul.children[0].cloneNode(true)表示ul拷贝第一个子节点(深拷贝)
- node.cloneNode() 参数为true时,表示深拷贝
- 深拷贝会复制节点及内容,包括里面的所有子节点等
6.事件高级
1.注册事件的两种方式
注册事件(绑定事件)时,有这两种方式: 1.·传统方式
2.方法监听注册事件
示例:
<button>传统方式注册事件</button>
<button>方法监听注册事件</button>
<button>ie9以前的attachEvent</button>
1.传统注册事件
element.onclick
// 1.获取事件源
var btns = document.querySelectorAll('button');
// 2.注册事件 3.事件处理函数
btns[0].onclick = function () {
alert('22');
}
btns[0].onclick = function () {
alert('33'); // btns[0]执行此onclick
}
-
传统方式注册事件具有唯一性
-
唯一性
:同一个元素同一个事件只能设置一个处理函数,后面注册的处理函数覆盖之前注册的处理函数)
2.方法监听注册事件
eventTarget.addEventListener(type,listenner[,useCaptrue])
btns[1].addEventListener('click', function () {
alert('22');
})
btns[1].addEventListener('click', function () {
alert('33');
})
type
: 事件类型字符串,比如click,mouseover,没有on
前缀listener
: 事件监听函数,事件发生时,会调用该函数useCapture
: 可选参数,是一个布尔值,默认是false
。addEventListener()
注册事件同一个元素,同一个事件可以添加多个监听器,ie9
以上支持该方法(常用)
attachEvent(EventNameWithOn,callback)
btns[2].attachEvent('onclick', function () {
alert('44');
EventNameWithOn
: 事件类型字符串,有on前缀callback
: 回调函数attachEvent()
:注册事件是ie9以前的版本,不常用了
如果可能存在不兼容性的浏览器版本时,需要注册事件兼容性解决方案:
function addEventListener(Element, eventName, fn) {
// 判断当前浏览器是否支持 addEventListener方法
if (element.addEventListener) {
element.addEventListener(eventName, fn);
} else if (element.attachEvent) {
element.attachEvent('on' + eventName, fn);
} else {
element['on' + eventName] = fn;
}
}
2.删除事件的两种方式
删除(解绑事件)时,有这两种方式: 1.传统删除事件
2.方法监听删除事件
示例:
<style>
div {
width: 100px;
height: 100px;
background-color: pink;
}
</style>
<div>1</div>
<div>2</div>
<div>3</div>
1.传统删除事件
div.onclick = null
var div = document.querySelectorAll('div');
div[0].onclick = function () {
alert(11);
div.onclick = null;
}
2.方法监听删除事件
removeEventListener()
div[1].addEventListener('click', fn);
function fn() {
alert(22);
div[1].removeEventListener('click', fn);
}
- removeEventListener()支持ie9以上版本浏览器(常用)
detachEvent()
div[2].attachEvent('onclick', fn2);
function fn2() {
alert(33);
div[2].detachEvent('onclick', fn2);
- detachEvent()为了照顾低版本浏览器(不常用)
如果可能存在不兼容性的浏览器版本时,需要解绑事件兼容性解决方案:
function removeEventListener(element, eventName, fn) {
if (element.removeEventListener) {
element.removeEventListener(eventName, fn);
} else if (element.detachEvent) {
element.detachEvent('on' + eventName, fn);
} else {
element['on' + eventName] = null;
}
3.事件流
DOM事件流:事件发生会在元素节点之间按照特定的顺序传播.这个传播过程即DOM事件流
DOM事件流三阶段: 1.捕获阶段
2.当前目标阶段
3.冒泡阶段
示例:
<style>
div {
margin: 200px auto;
}
.father {
position: relative;
width: 300px;
height: 300px;
background-color: pink;
}
.son {
position: absolute;
width: 200px;
height: 200px;
top: 50%;
left: 50%;
margin-left: -100px;
margin-top: -100px;
background-color: purple;
}
</style>
<div class="father">
<div class="son"></div>
</div>
// 捕获阶段
var son = document.querySelector('.son');
son.addEventListener('click', function () {
alert('son');
}, true)
var father = document.querySelector('.father');
father.addEventListener('click', function () {
alert('father');
}, true)
// 冒泡阶段
var son = document.querySelector('.son');
son.addEventListener('click', function () {
alert('son');
}, false)
var father = document.querySelector('.father');
father.addEventListener('click', function () {
alert('father');
}, false)
-
如果addEventListener第三个参数是
true
,则处于捕获阶段:document
->html
->body
->father
->son
-
如果addEventListener第三个参数是false 则处于冒泡阶段:
son
->father
->body
->html
->document
(实际开发中更关注事件冒泡)
小结:
- js代码只能执行捕获或者冒泡中的其中一个
- onclick和attachment()只能获得冒泡阶段
- 捕获/冒泡阶段 addEventListener(type,listenner[,useCaptrue]) 第三个参数useCaptrue为true(捕获)/false(冒泡)
4.事件对象
当事件发生后,跟事件相关的一系列信息数据的集合都会放在这个对象里面,这个对象就是event
,它有很多属性和方法。
示例:
<style>
div {
width: 100px;
height: 100px;
background-color: pink;
}
</style>
// 获取事件对象e
// 传统方式
div.onclick = function (e) {
console.log(e);
// 事件监听方式
var div = document.querySelector('div');
div.addEventListener('click', function (e) {
console.log(e);
})
- event就是一个事件对象,写到我们的侦听函数中,作为形参
- 事件对象有了事件才会存在,它是系统自定给我们创建的,我们不需要传递实参
- 事件对象是一系列相关数据的集合
- 事件对象我们可以自己命名,如event,evt,e等
如果可是低版本浏览器或者可能存在不兼容性的浏览器版本时:
div.onclick = function (e) {
// ie678 获取 照顾低版本浏览器
console.log(window.e);
// 兼容性写法
e = e || window.event
5.常见事件对象的属性和方法
事件对象属性方法 | 说明 |
---|---|
e.target | 返回触发事件的对象(标准) |
e.srcElement | 返回触发事件的对象(照顾低版本浏览器 ie9以下) |
e.type | 返回事件的类型 |
e.preventDefault() | 阻止默认事件(方法 如不让链接跳转 标准) |
e.returnValue | 阻止默认事件(属性 照顾低版本浏览器 ie9以下) |
e.stopPropagation() | 阻止冒泡(方法 标准) |
e.cancelBubble | 阻止冒泡(属性 照顾低版本浏览器 ie9以下 ) |
示例:
<div>盒子</div>
<ul>
<li>li one</li>
<li>li two</li>
<li>li three</li>
</ul>
1.返回触发事件的对象
e.target
var div = document.querySelector('div');
div.addEventListener('click', function (e) {
console.log(e.target);
console.log(this);
})
var ul = document.querySelector('ul');
ul.addEventListener('click', function (e) {
console.log(e.target); // li 触发事件
console.log(this); // ul 注册事件
- e.target返回的是li,li是触发事件的对象(元素)
- this返回的是ul,ul是注册事件的对象(元素)
e.srcElement
console.log(e.currentTarget);
- e.srcElement为了照顾低版本浏览器
如果可能遇到兼容性问题,使用兼容性解决方案:
// 兼容性写法
div.onclick = function (e) {
e = e || window.event;
var target = e.target || e.srcElement;
console.log(target);
和this很像的属性: currentTarget
console.log(e.currentTarget);
- currentTarget不识别低版本浏览器,this最常用
2.获取事件类型
示例:
<div>123</div<div>123</div>
e.type
var div = document.querySelector('div');
div.addEventListener('click', fun);
div.addEventListener('mouseover', fun);
div.addEventListener('mouseout', fn);
function fun(e) {
console.log(e.type);
}
- e.type能获取到实际的类型如: click,mouseover,mouseout
3.阻止默认行为
示例:
<a href="www.baidu.com">百度</a>
<form action="www.baidu.com">
<input type="submit" value="提交" name="sub" id="">
</form>
(1)e.preventDefault()
var a = document.querySelector('a');
a.addEventListener('click', fn);
function fn(e) {
console.log(e.preventDefault()); // dom标准写法
}
- e.preventDefault()阻止默认行为,链接a不能跳转
(2)e.returnValue
a.onclick = function (e) {
console.log(e.returnValue);
}
- e.returnValue为了照顾低版本浏览器
return false
也能阻止默认行为
缺点: return终止函数,不能继续执行后面的代码了
4.阻止事件冒泡
事件冒泡的本身特性会带来坏处,也会带来好处,当冒泡具有坏处时,我们可以灵活的使用阻止冒泡。
示例:
<div class="father">
<div class="son"></div>
</div>
(1) e.stopPropagation()
var son = document.querySelector('.son');
son.addEventListener('click', function (e) {
alert('son');
e.stopPropagation(); // dom 标准
}, false)
- e.stopPropagation()阻止事件冒泡,son元素的事件不能向上层father冒泡
(2)e.cancelBubble = true
var son = document.querySelector('.son');
son.addEventListener('click', function (e) {
alert('son');
e.cancelBubble = true;
}, false)
- e.cancelBubble = true阻止冒泡事件照顾的是低版本浏览器
如果可能存在有兼容性问题时,解决兼容性方案:
if (e && e.stopPropagation()) {
e.stopPropagation()
} else {
window.event.cancelBubble = true;
}
5.事件委托
事件委托原理: 给父节点添加侦听器,利用事件冒泡影响每一个子节点。
示例:
ul>
<li>知否知否,应是绿肥红瘦</li>
<li>知否知否,应是绿肥红瘦</li>
<li>知否知否,应是绿肥红瘦</li>
<li>知否知否,应是绿肥红瘦</li>
</ul>
var ul = document.querySelector('ul');
ul.addEventListener('click', function (e) {
// alert('yeyeye~');
e.target.style.backgroundColor = 'pink';
})
- 点击每个 li 都会弹出对话框,以前需要给每个 li 注册事件,是非常辛苦的,而且访问 DOM 的次数越多,这会延长整个页面的交互就绪时间。
- 给ul设置了监听事件,点击子节点li时,li的点击向上层冒泡到了ul,而ul设置有事件监听,就能执行事件监听函数里的代码
- 事件委托作用: 我们只操作了一次DOM,
提高
了程序性能
6.常见鼠标事件
鼠标事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
oncontextmenu | 右键菜单触发 |
onselectstart | 选中文字触发 |
- 以上事件使用方法监听事件不需要加
on
前缀
示例:
<body>
这段文字不想用于分享
<body>
(1) 右键菜单
contextmenu
document.addEventListener('contextmenu', function (e) {
e.preventDefault(); // 阻止默认行为
})
- contextmenu:右键菜单,我们可以使用阻止默认行为来禁用右键菜单
(2)选中文字
selectstart
document.addEventListener('selectstart', function (e) {
e.preventDefault(); // 阻止默认行为
})
- selectstart:选中文字,我们可以使用阻止默认行为来禁止选中文字
7.鼠标事件对象
鼠标事件对象: MouseEvent
。
鼠标事件对象属性 | 说明 |
---|---|
e.clientX | 返回鼠标在可视区的坐标x |
e.clientY | 返回鼠标在可视区的坐标y |
e.pageX | 返回鼠标在页面的坐标x |
e.pageY | 返回鼠标在页面的坐标要y |
e.screenX | 返回鼠标在屏幕的坐标x |
e.screenY | 返回鼠标在屏幕的坐标y |
示例:
<style>
body {
height: 3000px;
}
</style>
鼠标事件对象的坐标属性
client
page
screen
document.addEventListener('click', function (e) {
// console.log(e);
// 1.client
console.log(e.clientX);
console.log(e.clientY);
// 2. page
console.log(e.pageX);
console.log(e.pageY);
// 3.screen
console.log(e.screenX);
console.log(e.screenY);
})
- client: 鼠标在可视区的坐标(x,y)
- page: 鼠标在页面的坐标(x,y)
- screen: 鼠标在屏幕的坐标(x,y)
8.常见的键盘事件
键盘事件 | 触发条件 |
---|---|
keyup | 某个键盘弹起触发 |
keydown | 某个键盘按下触发 |
keypress | 某个键盘按下触发(但不识别功能键 如ctrl,shift,方向键等) |
示例:
// 1.keyup
document.addEventListener('keyup', function () {
console.log('我弹起了!');
})
// 2.keydown
document.addEventListener('keydown', function () {
console.log('我按下了down');
})
// 3.keypress
document.addEventListener('keypress', function () {
console.log('我按下了press');
})
- 三者都触发时的顺序: keydown->keypress->keyup
9.键盘事件对象
键盘事件对象: KeyboardEvent
。
键盘事件对象属性 | 说明 |
---|---|
keyCode | 返回该键的ASCII值 |
键盘事件对象中的属性
keyCode
// keyup和keydown事件不能区分字的大小写 如a何A都是65
document.addEventListener('keyup', function (e) {
// e.keyCode
console.log('up:' + e.keyCode);
//
if (e.keyCode === 65) {
alert('您按下了A键');
} else {
alert('您没按下A键');
}
})
//
document.addEventListener('keypress', function (e) {
console.log('press:' + e.keyCode);
})
-
我们可以利用keyCode返回的
ASICC
值来判断用户按下了哪个键 -
keyup和keydown事件不能区分字的大小写 如: a何A都是65,keypress能区分键盘字母的大小写。
二.BOM
1.BOM简介
BOM
(Browser Object Model)即浏览器对象模型
,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是window
。
BOM由一系列相关的对象构成,并且每个对象都提供了很多方法和属性。
BOM缺乏标准,JavaScript语法的标准化组织是ECMA,DOM的标准化组织是W3C,BOM最初是Netscape浏览器标准的一部分。
- window对象是浏览器的
顶级对象
,它具有双重角色。 - 它是JS访问浏览器窗口的一个接口。
- 它是一个全局对象。定义在全局作用域中的变量、函数都会变成window的属性和方法,调用的时候是可以忽略window的,如
alert()
,prompt()
都属于window的方法
window下面的对象: document
, location
, navigation
,screen
,history
2.window对象的常见事件
windows对象的常见事件: 1.页面加载事件
2.调整窗口大小事件
。
- 页面加载事件:
load
、DOMContentLoaded
- 调整窗口大小事件:
resize
1.页面加载事件
有了window对象的页面加载事件,我们的js代码在哪个位置都能执行,它是等页面加载后才执行。
load
// 传统方式
window.onload = function () {
var btns = document.querySelector('button');
btns.onclick = function () {
alert(66);
}
}
window.onload = function () {
var btns = document.querySelector('button');
alert(77);
}
// 监听事件方式
window.addEventListener('load', function () {
var btns = document.querySelector('button');
btns.addEventListener('click', function () {
alert(88);
})
})
- load: 等页面内容全部加载后,执行load事件。
DOMContentLoaded
window.addEventListener('DOMContentLoaded', function () {
alert(11);
})
- DOMContentLoaded: 等DOM加载完毕,就执行DOMContentLoaded事件(ie9以上支持)
什么时候用DOMContentLoaded?
如果页面的图片很多的话,从用户访问到load触发可能需要较长的时间,交互效果就不能实现,必然影响用户体验,此时用DOMContentLoaded事件比较合适。
load和DOMContentLoaded的区别:
- DOMContentLoaded只是等DOM加载完毕就执行,不包含图片,flash,css等就可以执行,加载速度要比load快
2.调整窗口大小事件
resize
示例:
<style>
div {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
<div></div>
window.addEventListener('load', function () {
var btns = document.querySelector('div');
window.addEventListener('resize', function () {
// innerWidth能获取当前屏幕宽度
console.log(window.innerWidth);
console.log('窗口在大小变化');
if (innerWidth < 800) {
btns.style.display = 'none';
} else {
btns.style.display = 'block';
}
})
})
innerWidth
能获取当前屏幕宽度- 当窗口大小发生变化时,resize事件就会触发
- 我们可以利用resize做响应式效果,如以上例子屏幕宽度<800,则盒子隐藏
3.定时器
定时器有: 1. setTimeout()
2. setInterval()
(1)setTimeout(调用函数, [延迟的毫秒数])
// 写法方式1:匿名函数
setTimeout(function () {
console.log('BOMM!');
}, 3000); // 3秒
// 写法方式2:自定义函数
function callback() {
console.log('BOMM!');
}
var timer = setTimeout(callback, 3000);
// setTimeout('callback()', 3000); // 调用方式2(了解 不提倡这种写法)
- setTimeout()方法用于设置一个定时器,该定时器在定时器到期后执行调用函数
- setTimeout()方法的第一个参数是回调函数,第二个参数是延迟的毫秒数
清除setTimeout()定时器: clearTimeOut(timeoutID)
示例:
<button>停止定时器按钮</button>
// 清除定时器
//
var timer = setTimeout(function () {
console.log('BOOM!爆炸')
}, 5000);
var btns = document.querySelector('button');
btns.addEventListener('click', function () {
clearTimeout(timer);
})
-
clearTimeout() 可以清除setTimeout定时器,参数是定时器的名称
-
开发中,网页经常会有很多不同的定时器,所以我们经常给定时器加上
标识
(名字) -
以上例子当点击button时,就可以清除定时器timer
(2) setInterval(回调函数,延迟时间)
setInterval(function () {
console.log('继续输出!');
}, 1000);
- setInterval()用法全都和setTimeout()一样
清除setInterval()定时器: clearInterval(timeoutID)
示例:
<button class="begin">开始定时器</button>
<button class="stop">结束定时器</button>
var begin = document.querySelector('.begin');
var stop = document.querySelector('.stop');
var timer = null; // timer 全局变量(这样其他的函数就能访问到它了) null是一个空对象
begin.addEventListener('click', function () {
// 1.开启定时器
timer = setInterval(function () {
console.log('how are you?')
}, 1000)
})
stop.addEventListener('click', function () {
// 2.结束定时器
clearInterval(timer);
})
- clearInterval()可以清除setInterval()定时器
setInterval()和setTimeout()的区别: setInterval()
是每隔多少时间然后去执行回调函数,可以重复执行
很多次。setTimeout()
是只能执行一次
。
4.JS执行机制
1.JS单线程
JavaScript最大的特点就是单线程
,也就是说,同一个时间下,只能做一件事。这是因为JavaScript这门脚本语言诞生的使命所致。
单线程所有任务都需要排队,前一个任务结束,才会执行后一个任务。这样会使JS执行的时间过长,这样就会造成页面的渲染效果不连贯,导致页面渲染加载阻塞的感觉。
2.JS同步和异步
为了解决单线程存在的问题, 利用多核cpu的计算能力, HTML5提出Web Worker标准, 允许JavaScript脚本创建多个线程, 于是就有了同步和异步。
-
同步
: 前一个任务执行结束后再执行下一个任务(排队的形式),程序的执行顺序与任务的排列顺序是一致的、同步的。 -
异步
: 执行一个任务的同时另一个任务也可以执行。
3.JS同步异步执行过程
JS中把所有任务分为了: 1.同步任务
2.异步任务
。
-
同步任务
: 同步任务都在主线程上执行,形成一个执行栈。 -
异步任务
: 异步任务都是通过回调函数
了来实现的。异步任务相关的回调函数会添加到任务队列(消息队列)
中。 -
异步任务一般有三种: 1.
普通事件
,如: click,resize 2.资源加载
,如: load,error等 3.定时器
,如: setTimeout,setInterval。
执行过程:
1.先执行执行栈中的同步任务
2.异步任务(回调函数)放入消息队列中
3.一旦执行栈中的所有同步任务执行完毕,系统将按次序读取消息队列中的异步任务,被读取的异步任务结束等待状态,进入执行栈中,开始执行。
5.location对象
window给我们提供了一个location
属性用于获取或设置页面的url,并且可以解析url。这个属性返回的是一个对象,所以我们也称这个属性为location对象。
1.URL
统一资源定位符
(Uniform Resource Locator,URL
)是互联网上标准资源的地址。 互联网上的每个文件都有一个唯一的URL,它包含信息指出文件的位置以及浏览器应该怎么去处理它。
//URL一般语法格式
protocol://host[:port]/path/[?query]#fragment
protocol
: 通信协议,常用的http,ftp,maito
等host
:主机名(域名) www.xxx.comport
: 端口号(可选参数),省略时使用的是默认端口,如http默认端口为80
path
:路径,由0个或者多个’/
'符号隔开的字符串,一般用来表示主机上的一个目录或文件地址query
: 参数 以键值对的形式 '&
'符号分隔开fragment
: 片段#
后面内容 常见于链接(锚点)
2.location对象的属性
location对象属性 | 返回值 |
---|---|
location.href | 获取或设置整个url |
location.host | 返回主机(域名): www.xxx.com |
location.port | 返回端口号 |
location.pathname | 返回路径 |
location.search | 返回参数( ?后面的内容) |
location.hash | 返回片段(#后面的内容 常见于锚点链接) |
location对象属性使用,如:
获取url地址
location.url
设置url地址
location.url = 'http://www.xxx.com'
3.location对象方法
location对象方法 | 返回值 |
---|---|
location.assign() | 跟href一样,可以跳转页面(重定向页面) 能记录历史 回退页面 |
location.replace() | 替换当前页面,不记录历史,不能回退页面 |
location.reload() | 重新加载页面,相当于刷新(f5) 参数为true(强制刷新) ctrl+f5 |
location对象方法使用,如:
重定向页面
location.assign('http://www.xxx.com');
6.navigator对象
navigator
对象包含有关浏览器的信息,它有很多属性,我们最常用的是userAgent
。
userAgent属性可以返回客户端发送服务端的user-agent头部的值。通过user-agent头部的值,我们可以判断用户是以哪个终端打开页面,然后实现相应的跳转方式。
示例:
if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
window.location.href = "./m.jd"; // 手机
} else {
window.location.href = "./www.jd.com"; //电脑
}
if(navigator.userAgent.match(/(移动端类型))) {}
7.history对象
window对象给我们提供了一个history
对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的url。
history对象方法 | 作用 |
---|---|
back() | 后退功能 |
forword() | 前进功能 |
go(参数) | 前进后退功能,参数如果是1,则前进一个页面,-1,则后退一个页面 |
history对象方法使用,如:
后退一页
history.go(-1);
|
| ----------------- | ------------------------------------ |
| location.href | 获取或设置整个url |
| location.host | 返回主机(域名): www.xxx.com |
| location.port | 返回端口号 |
| location.pathname | 返回路径 |
| location.search | 返回参数( ?后面的内容) |
| location.hash | 返回片段(#后面的内容 常见于锚点链接) |
location对象属性使用,如:
获取url地址
location.url
设置url地址
location.url = 'http://www.xxx.com'
3.location对象方法
location对象方法 | 返回值 |
---|---|
location.assign() | 跟href一样,可以跳转页面(重定向页面) 能记录历史 回退页面 |
location.replace() | 替换当前页面,不记录历史,不能回退页面 |
location.reload() | 重新加载页面,相当于刷新(f5) 参数为true(强制刷新) ctrl+f5 |
location对象方法使用,如:
重定向页面
location.assign('http://www.xxx.com');
6.navigator对象
navigator
对象包含有关浏览器的信息,它有很多属性,我们最常用的是userAgent
。
userAgent属性可以返回客户端发送服务端的user-agent头部的值。通过user-agent头部的值,我们可以判断用户是以哪个终端打开页面,然后实现相应的跳转方式。
示例:
if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
window.location.href = "./m.jd"; // 手机
} else {
window.location.href = "./www.jd.com"; //电脑
}
if(navigator.userAgent.match(/(移动端类型))) {}
7.history对象
window对象给我们提供了一个history
对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的url。
history对象方法 | 作用 |
---|---|
back() | 后退功能 |
forword() | 前进功能 |
go(参数) | 前进后退功能,参数如果是1,则前进一个页面,-1,则后退一个页面 |
history对象方法使用,如:
后退一页
history.go(-1);