视频教程:黑马程序员 pink老师 DOM BOM操作
DOM
什么是DOM
文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML、XML)的标准编程接口。
W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的样式、内容和结构。
DOM树
- 文档:一个页面就是一个文档,DOM中就是Document
- 元素:页面中的所有标签就是元素,DOM中就是element
- 节点:页面中的所有内容都是节点,包括标签、属性href、文本、注释等,DOM中就是node
获取页面中的element元素
有四种方式:
- 根据ID获取
var e1 = document.getElementsById('id name')
返回的结果是一个元素对象,如<div id="id name">this is element content</div>
,我们可以使用console.dir(e1)
查看这个对象拥有的属性和方法 - 根据标签名获取
var e2 = document.getElementsByTagName('div')
返回的结果是标签对象的集合(伪数组),如没有符合标签对象,则返回空伪数组 - 通过HTML5新增方式获取
1.根据类名获得元素
var b1 = document.getElementsByClassName('ClassName');
2.返回指定选择器的第一个元素 类名加. id名加# 标签不加符号
var b2 = document.querySelector('.ClassName');
3.返回指定选择器的全部元素的伪数组 同上
var b3 = document.querySelectorAll('#IdName');
- 特殊元素获取(body, html)
获取body元素:var bodyEle = document.body;
获取html元素:var htmlELe = document.documentElement;
PS:可以级联获取元素,即e1.getElementByTagName(‘li’)
事件三要素
- 事件源(哪个元素)
- 事件类型(什么事件才触发)
- 事件处理程序(执行什么)
执行事件的步骤:
- 获取事件源
- 注册事件(绑定事件)
- 添加事件处理程序(采用函数赋值的形式)
例子:实现点击按钮后弹出对话框
1.获取事件源(按钮)
var btn = document.querySelector('button');
2.注册事件 + 函数赋值处理程序
btn.onclick = function() {
alert("点击按钮了");
}
改变元素内容
element.innerText
和element.innerHTML
前者会替换标签内的全部内容,但是去除html标签、空格和换行。
后者会替换标签内的全部内容,且支持html标签和保留空格、换行。
var ele = document.querySelector('div');
ele.innerText = "替换后的内容";
同理,也可以改变标签的各种属性,src,href,id,alt,title
等。
改变元素样式
element.style
可以改变元素的样式,并作为行内样式
element.className
可以对类名进行修改,直接覆盖原有类名
<div>123</div>
<script>
var div = document.querySelector("div");
div.onclick = function () {
this.style.backgroundColor = this.style.backgroundColor === "pink" ? "purple" : "pink";
}
</script>
常用元素api
element.onfocus
获得焦点
element.onblur
失去焦点
element.onmouseover
鼠标经过
element.onmouseout
鼠标离开
获取、修改和删除 元素的属性值
- 获取属性值:
element.属性
用于获取元素本身自带的属性element.getAttribute('属性名')
用于获取自定义属性
- 修改属性值:
element.属性
用于修改元素本身自带的属性的值element.setAttribute('属性名', 值)
用于修改自定义属性的值
- 获取属性值:
element.removeAttribute('属性名')
用于删除元素的属性
H5新增方式
H5规定自定义属性需以data-
开头
例如:<div data-index="2"></div>
同时也新增了一个获取自定义属性的方式:
<div data-index="2"></div>
---
var ele = document.querySelector("div");
ele.dataset.index // 2
ele.dataset['index'] // 2
节点操作
网页中的所有内容都是节点(标签、属性、文本、注释和空格换行等),在DOM中,节点使用node表示。
节点至少有三个属性:nodeType、nodeName、nodeValue
节点分为三类:
- 元素节点 nodeType=1
- 属性节点 nodeType=2
- 文本节点 nodeType=3 (包含文字、空格和换行)
利用DOM树可以把节点划分为不同的层级关系,常见的是父子兄层级关系。
父级节点
node.parentNode
返回node节点的父节点,且仅返回最近的一个父节点,如无父节点,则返回null。
子级节点
查找子节点
- 标准方式:
node.childNodes
返回node节点的子节点的集合,包括元素节点、文本节点等。 - 非标准方式:
node.children
是一个只读的属性,返回node节点的所有子元素节点,它只返回元素节点,不返回其他类型节点。
查找首末子节点
-
标准方式:
node.firstChild
返回第一个子节点(所有类型节点),没有则null
node.lastChild
返回最后一个子节点(所有类型节点) -
IE9以上支持的方法:
node.firstElementChild
返回第一个元素节点,找不到则返回null
node.lastElementChild
返回最后一个元素节点
兄弟节点
查找兄弟节点
- 标准方式:
node.nextSibling
返回node节点的下一个兄弟节点,包括元素节点、文本节点等,找不到则返回null。
node.previousSibling
返回node节点的上一个兄弟节点,包括元素节点、文本节点等,找不到则返回null。 - 非标准方式(只兼容IE9以上):
node.nextElementSibling
返回node节点的下一个兄弟节点,仅元素节点,找不到则返回null。
node.previousElementSibling
返回node节点的上一个兄弟节点,仅元素节点,找不到则返回null。
创建节点
方法一
想要在页面中添加一个节点,需要有两步:1 创建节点,2 添加节点至指定位置
var child = document.createElement('tagName')
创建由tagName指定的标签元素,这一步骤可称为动态创建元素节点。
node.appendChild(child)
将一个节点添加到指定父节点下的子节点列表的末尾,类似于CSS中after伪元素。
node.insertBefore(child, 指定节点)
指定节点常见写法:node.children[0]
将一个节点添加到指定父节点(node)下指定节点的前面,类似于CSS中before伪元素。
方法二
element.innerHTML = '<a>123</a>'
直接对元素内部进行文本的书写
方法三
document.write()
是直接将内容写入页面的内容流,但是当文档流执行完毕后进行这一操作,就会导致页面全部重绘(即原先元素消失,仅存在新写的内容)。
方法一与方法二对比
innerHTML
创建大量元素的效率更高,注意不能使用循环字符串拼接方式,要用数组集合再join的方式,实现结构相对复杂
createElement() + appendChild()/insertBefore()
的效率相对低一点点,但是结构清晰,实现简单。
总结:innerHTML
在创建大量元素时效率比createElement
高
删除节点
node.removeChild(child)
删除一个node下的子节点,返回删除的节点
例:
var el = document.querySelector('ul');
el.removeChild(el.children[0]); //删除ul中的第一个元素节点
复制节点(克隆)
node.cloneNode()
返回node节点的一个副本
括号参数为空或false,则是浅拷贝,只复制节点本身,不复制里面的子节点;
括号参数为 true,则是深拷贝,会复制节点本身及其里面的所有子节点。
事件高级
注册事件
给元素添加事件,称为注册事件或绑定事件。
注册事件有两种方式,传统方式和方法监听注册方式。
addEventListener
事件监听方式
使用方法:eventTarget.addEventListener(type, listener[, useCapture])
该方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。
该方法接收3个参数:
type
:事件类型字符串,如 click, mouseover等,此时不带on
listener
:事件处理函数,事件发生时会调用该函数useCapture
:可选参数,是一个布尔值,默认为false,为true时是在事件捕获阶段调用事件处理函数,为false或省略时是事件冒泡阶段调用事件处理函数。
例:
var el = document.querySelector('button');
el.addEventListener('click', function() {
alert('按下了按钮');
})
仅IE9及以后支持该方法
attachEvent
事件监听方式
该方法不常用,当需要支持IE8及之前版本浏览器时,使用element.onclick = function() {}
更方便。
删除事件
传统注册方式
eventTarget.onclick = null;
方法监听注册方式
IE9及以上:eventTarget.removeEventListener(type, listener[, useCapture]);
例:
var el = document.querySelector('button');
el.addEventListener('click', fn)
function fn() {
alert('按下了按钮');
// 第二次开始不执行
el.removeEventListener('click', fn)
}
IE8及以下:eventTarget.detachEvent(eventNameWithOn, callback)
DOM事件流
事件流描述的是从页面中接收事件的顺序。
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程就是DOM事件流。
<body>
<div class="father">
<div class="son">son盒子</div>
</div>
<script>
// dom 事件流 三个阶段
// 1. JS 代码中只能执行捕获或者冒泡其中的一个阶段。
// 2. onclick 和 attachEvent(ie) 只能得到冒泡阶段。
// 3. 捕获阶段 如果addEventListener 第三个参数是 true 那么则处于捕获阶段 document -> html -> body -> father -> son
var son = document.querySelector('.son');
son.addEventListener('click', function() {
alert('son');
}, true);
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
}, true);
// 4. 冒泡阶段 如果addEventListener 第三个参数是 false 或者 省略 那么则处于冒泡阶段 son -> father ->body -> html -> document
var son = document.querySelector('.son');
son.addEventListener('click', function() {
alert('son');
}, false);
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
}, false);
</script>
</body>
上述例子中,在捕获阶段,点击内部元素son盒子
,会先触发最外部father
的点击事件,再触发内部son
的点击事件;
在冒泡阶段,点击内部元素son盒子
,会先触发最内部son
的点击事件,再触发外部father
的点击事件。
注意事项:
- JS代码中只能执行捕获或冒泡二选一,一个阶段
- 使用attachEvent + onclick,只能得到冒泡阶段
- 实际开发中事件冒泡更为常用
- 有些事件没有冒泡过程,如:
onblur, onfocus, onmouseenter, onmouseleave
事件对象
事件对象就是事件发生时的各种状态集合,代表着事件的状态
简单理解就是:事件发生后,和事件相关的一系列信息数据的集合都放在这个对象里面,这个对象就是事件对象event,它有很多属性和方法。
使用方法
eventTarget.onclick = function (event) {
// 此时的event就是事件对象,还可以简写为e
}
eventTarget.addEventListener('click', function (e) {
// 此时的e就是事件对象,等价于event
})
event 是形参,系统帮我们设定为事件对象,不需要传递实参过去,当我们注册事件时,event 对象会由系统自动创建,并依次传递给事件监听器(事件处理函数)。
兼容性方法
在IE6~IE8中,不兼容上述的event事件对象,需要通过在window.event
中获取。
解决方案:
e = e || window.event
事件对象常用属性及方法
target
e.target
属性,返回的是触发事件的对象(元素),而在事件处理函数中的this则是该事件所绑定的对象(元素)。
<body>
<div>123</div>
<ul>
<li>abc</li>
<li>abc</li>
<li>abc</li>
</ul>
<script>
// 常见事件对象的属性和方法
// 1. e.target 返回的是触发事件的对象(元素) this 返回的是绑定事件的对象(元素)
// 区别 : e.target 点击了那个元素,就返回那个元素 this 那个元素绑定了这个点击事件,那么就返回谁
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) {
// 我们给ul 绑定了事件 那么this 就指向ul
console.log(this);
console.log(e.currentTarget);
// e.target 指向我们点击的那个对象 谁触发了这个事件 我们点击的是li e.target 指向的就是li
console.log(e.target);
})
// 了解兼容性
// div.onclick = function(e) {
// e = e || window.event;
// var target = e.target || e.srcElement;
// console.log(target);
// }
// 2. 了解 跟 this 有个非常相似的属性 currentTarget ie678不认识
</script>
</body>
阻止默认行为 e.preventDefault()
<body>
<div>123</div>
<a href="http://www.baidu.com">百度</a>
<form action="http://www.baidu.com">
<input type="submit" value="提交" name="sub">
</form>
<script>
// 常见事件对象的属性和方法
// 1. 返回事件类型
var div = document.querySelector('div');
div.addEventListener('click', fn);
div.addEventListener('mouseover', fn);
div.addEventListener('mouseout', fn);
function fn(e) {
console.log(e.type);
}
// 2. 阻止默认行为(事件) 让链接不跳转 或者让提交按钮不提交
var a = document.querySelector('a');
a.addEventListener('click', function(e) {
e.preventDefault(); // dom 标准写法
})
// 3. 传统的注册方式
a.onclick = function(e) {
// 普通浏览器 e.preventDefault(); 方法
// e.preventDefault();
// 低版本浏览器 ie678 returnValue 属性
// e.returnValue;
// 我们可以利用return false 也能阻止默认行为 没有兼容性问题 特点: return 后面的代码不执行了, 而且只限于传统的注册方式
return false;
alert(11);
}
</script>
</body>
阻止事件冒泡
共两种方式:
- 标准写法:
e.stopPropagation()
- 非标准写法(兼容ie6,7,8):
e.cancelBubble = true
orwindow.event.cancelBubble = true
// 常见事件对象的属性和方法
// 阻止冒泡 dom 推荐的标准 stopPropagation()
var son = document.querySelector('.son');
son.addEventListener('click', function(e) {
alert('son');
e.stopPropagation(); // stop 停止 Propagation 传播
e.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡
}, false);
事件委托(代理、委派)
事件委托,在jQuery中被称为事件委派。
实现原理:不在每个子节点(li)上分别设置事件监听器,而在父节点(ul)上设置一个事件监听器,利用冒泡原理,每次点击子节点都会结果冒泡行为而触发父节点的事件。
作用:减少了我们对DOM的操作次数,提高代码的性能。
例子:对上述例子实现功能,点击每个小li则改变该li的背景颜色
<body>
<ul>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
</ul>
<script>
// 事件委托的核心原理:给父节点添加侦听器, 利用事件冒泡影响每一个子节点
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
// alert('知否知否,点我应有弹框在手!');
// e.target 这个可以得到我们点击的对象
// 每次触发ul的事件后,通过e.target得到当前li,再修改其背景颜色
e.target.style.backgroundColor = 'pink';
})
</script>
</body>
常用的鼠标事件
- 禁止鼠标右键菜单
document.addEventListener('contextmenu', function (e) {
e.preventDefault();
})
- 禁止鼠标选中(文字等)
document.addEventListener('selectstart', function (e) {
e.preventDefault();
})
- 获取鼠标坐标(三种坐标)
// 鼠标事件对象 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);
})
常用的键盘事件
注意:
- 如果使用
addEventListener
,不需要加on
onleypress
不能识别功能键- 假设三个事件都绑定在一个元素上,执行顺序是
keydown - keypress - keyup
同样的,键盘事件处理函数中的event
就是键盘事件对象,包含属性有按键的值,ASCII码等。
keyup和keydown不区分字母大小写,keypress可以区分大小写(即ASCII码是否区分)
前两者可以区分所有的键盘按键(包含功能键等),而后者keypress不识别功能键,但是keyCode能区分大小写。
BOM
BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是window
。
BOM由一系列相关的对象构成,并且每个对象都提供了很多方法和属性。
BOM缺乏标准,JavaScript语法的标准化组织是ECMA,DOM的标准化组织是W3C,而BOM最初是NetScape网景公司浏览器标准的一部分。
BOM的构成:
window
对象是浏览器的顶级对象,它具有双重角色:
- 它是JS访问浏览器窗口的一个接口
- 它是一个全局对象,定义在全局作用域中的变量、函数都会变成window对象的属性和方法
在调用window的属性和方法时可以省略window,如alert()
、prompt()
都是window的方法。
注意:window有一个特殊的属性:window.name,它的值为空字符串""
window对象的常见事件
窗口加载事件
传统注册方法:window.onload = function () {}
监听事件方法:window.addEventListener('load', function() {})
window.onload
是窗口(页面)加载事件,当文档内容完全加载完成后就会触发该事件(包括图像、css、脚本文件等)。
注意:
- 使用窗口加载事件后,就可以将onload事件处理函数的JS代码写到HTML元素的前面位置,因为onload中的JS代码会在文档全部加载后才执行
window.onload
的传统注册方式只可注册一次,如果注册多个则以最后一个为准- 使用
addEventListener()
可无限制注册
额外方法:
document.addEventListener('DOMContentLoaded', function () {})
与上面两种方法不同,该事件仅当DOM加载完成后就会触发,不需要等待CSS、图片、flash等加载完成。
IE9及以上支持该方法
使用环境:
如果页面的图片较多,那么用前两种方法的话触发事件就会比较慢,需要等图片加载完成,而使用第三种方法就可以在页面基本元素加载完后就触发事件。
调整窗口大小事件
传统注册方法:window.onresize = function () {}
监听事件方法:window.addEventListener('resize', function() {})
当浏览器窗口被调整时,就会触发该事件。
window.innerWidth
:当前屏幕的宽度
我们可以利用这个方法来完成响应式布局(根据屏幕大小来调整页面布局)。
定时器
window对象共提供了两种定时器方法:
1: setTimeout()
2: setInterval()
setTimeout()
定时器
window.setTimeout(调用function, [延迟毫秒数]);
该方法用于设置一个定时器,在定时器到期后执行调用函数。
注意:
window
可以省略- 调用函数可以直接定义匿名函数,或填写函数名及采用字符串形式
setTimeout(function () {...}, 2000);
setTimeout(fn, 2000);
setTimeout('fn()', 2000);
- 定时器延迟的毫秒数可以不填,默认为0
- 这个调用函数也可以称为回调函数,前文讲的
element,onclick = function() {}
这里的函数也是回调函数
停止定时器:
window.clearTimeout(定时器名字)
用于取消指定的定时器。
var timer = setTimeout(function () {...}, 2000);
clearTimeout(timer);
setInterval()
定时器
功能和用法与setTimeout()
几乎一致,只是它的定时是每隔指定时间就执行一次回调函数,即循环定时。
停止定时器:
window.clearInterval(定时器名字)
用于取消指定的定时器。
var timer = setInterval(function () {...}, 2000);
clearInterval(timer);
this
的指向
// this 指向问题 一般情况下this的最终指向的是那个调用它的对象
// 1. 全局作用域或者普通函数中this指向全局对象window( 注意定时器里面的this指向window)
console.log(this);
function fn() {
console.log(this);
}
window.fn();
window.setTimeout(function() {
console.log(this);
}, 1000);
// 2. 方法调用中谁调用this指向谁
var o = {
sayHi: function() {
console.log(this); // this指向的是 o 这个对象
}
}
o.sayHi();
var btn = document.querySelector('button');
// btn.onclick = function() {
// console.log(this); // this指向的是btn这个按钮对象
// }
btn.addEventListener('click', function() {
console.log(this); // this指向的是btn这个按钮对象
})
// 3. 构造函数中this指向构造函数的实例
function Fun() {
console.log(this); // this 指向的是fun 实例对象
}
var fun = new Fun();
JavaScript执行机制
JavaScript是单线程的,为了解决单线程导致的页面渲染加载阻塞问题,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,于是就有了同步和异步。
同步和异步
同步任务:
同步任务都在主线程上执行,形成一个执行栈。
异步任务:
JS的异步是通过回调函数实现的,一般而言异步任务有以下三种类型:
- 普通事件,如click、resize等
- 资源加载,如load、error等
- 定时器,包括setTimeout、setInterval等
异步任务的相关回调函数会添加到任务队列中(消息队列)。
执行机制
- 先执行执行栈中的同步任务,从上到下按序执行
- 将异步任务(回调函数)放入任务队列中
- 当执行栈中的任务都完成后,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈开始执行
由于主线程不断地重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环(event loop)。
location对象
什么是location对象
window对象向我们提供了一个location属性,用于获取或设置窗体的URL,并且可以解析URL,因为这个属性返回的值是对象类型,因此也叫location属性为location对象。
URL 统一资源定位符
**统一资源定位符(Uniform Resource Locator)**是互联网标准资源的地址,互联网上每个文件(资源)都有其唯一的URL,它包含的信息指出了文件的位置以及告诉浏览器应该如何处理它。
URL的一般格式为:
protocol://host[:port]/path/[?query]#fragment
https://editor.csdn.net/md?articleId=113779983
location对象的属性
location对象的常见方法
navigator 对象
navigator对象包含有关浏览器的信息,最常用的属性是userAgent,该属性返回由客户机发送给服务器的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.com"; //手机
} else {
window.location.href = "jd.com"; //电脑
}
history 对象
window对象给我们提供了一个history对象,用于喝浏览器的历史记录进行交互,该对象包含用户在当前窗口中访问过的url。
PC端网页特效
元素偏移量 offset
offset就是偏移量,通过它的相关属性可以动态的得到元素的位置、大小等。
- 获得元素距离带有定位的父元素的偏移量
- 获得元素自身的大小(width、height)
- 返回的数值是不包括单位的
offset系列常用属性:
offset与style的区别:
元素可视区 client
使用client的相关属性来获取元素可视区域的相关信息,包括元素大小、边框大小等。
立即执行函数
(function() {})()
或 (function() {}())
主要作用:创建一个独立的作用域,避免了不同js文件同时使用时的命名冲突问题。
元素滚动 scroll
使用scroll的相关属性可以动态获得元素的大小、滚动距离等。
如果浏览器的高(或宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发 onscroll 事件。
三个系列总结
他们的主要用法区别:
- offset系列 经常用于获得元素位置 offsetLeft offsetTop
- client 经常用于获取元素大小 clientWidth clientHeight
- scroll 经常用于获取滚动距离 scrollTop scrollLeft
- 注意页面滚动的距离通过 window.pageXOffset 获得
mouseenter和mouseover的区别
mouseenter鼠标事件:
- 当鼠标移动到元素上时就会触发 mouseenter 事件
- 类似 mouseover,它们两者之间的差别是:
- mouseover 鼠标经过自身盒子会触发,经过子元素盒子还会触发。 mouseenter 只会经过自身盒子触发
- 之所以这样,是因为mouseenter不会冒泡,而mouseover会冒泡,触发子盒子后冒泡触发自身盒子
- 跟mouseenter搭配 鼠标离开
mouseleave
同样不会冒泡
动画
实现原理
通过定时器setInterval()
不断移动盒子的位置。
实现步骤:
- 获得盒子的当前位置
- 让盒子在当前位置上加上一个要移动的距离
- 利用定时器不断重复 1,2步骤
- 设置一个结束定时器的条件
- 移动距离
element.style.left
,需要该元素position: absolute
定位
缓动效果原理
缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来。
实现思路:
- 让盒子每次移动的距离慢慢变小,这样速度就会慢慢落下来
- 核心算法:(目标位置 - 现在位置) / 10 = 每次移动的步长
- 停止条件:当前盒子位置 = 目标位置就停止定时器
- 当步长为正数时,需要向上取整;步长值为负数时,需要向下取整,不然会到达不了目标位置
回调函数
原理:函数可以作为一个参数,将这个函数作为参数传到另一个函数中,当那个函数执行完成后,再执行传进去的这个函数,整个过程就叫做回调。
简单动画实现的样例:
function animate(obj, target, callback) {
// console.log(callback); callback = function() {} 调用的时候 callback()
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
// var step = Math.ceil((target - obj.offsetLeft) / 10);
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
// if (callback) {
// // 调用函数
// callback();
// }
callback && callback();
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}
移动端网页特效
触屏事件
touch对象代表一个触摸点。触屏事件可响应用户手指(或触控笔)对屏幕的操作。
常见的触屏事件:
触摸事件对象(TouchEvent)
TouchEvent是一类描述手指在触摸平面的状态变化的事件,可以用于描述一个或多个触点。
touchstart、touchmove、touchend三个事件有各自的事件对象。
常见触摸事件对象的属性:
移动端拖动元素
- touchstart、touchmove、touchend 可以实现拖动元素
- 但是拖动元素需要当前手指的坐标值 我们可以使用 targetTouches[0] 里面的pageX 和 pageY
- 移动端拖动的原理: 手指移动中,计算出手指移动的距离。然后用盒子原来的位置 + 手指移动的距离
- 手指移动的距离: 手指滑动中的位置 减去 手指刚开始触摸的位置
拖动元素三步曲:
(1) 触摸元素 touchstart: 获取手指初始坐标,同时获得盒子原来的位置
(2) 移动手指 touchmove: 计算手指的滑动距离,并且移动盒子
(3) 离开手指 touchend: 无需事件操作
注意: 手指移动也会触发滚动屏幕所以这里要阻止默认的屏幕滚动 e.preventDefault();
classList属性
classList属性是HTML5新增的属性,可以返回元素的类名数组,仅ie10以上版本支持。
该属性一般用于在元素中添加、移除及切换CSS类。
该属性有以下方法:
- 添加类名:
element.classList.add('className')
- 移除类名:
element.classList.remove('className')
- 切换类:
element.classList.toggle('className')
本地存储
随着互联网的快速发展,基于网页的应用越来越普遍,同时也变的越来越复杂,为了满足各种各样的需求,会经常性在本地存储大量的数据,HTML5规范提出了相关解决方案。
本地存储具有的特性:
- 数据存储在用户浏览器中
- 设置、读取方便、甚至页面刷新不丢失数据
- 容量较大,sessionStorage约5M、localStorage约20M
- 只能存储字符串,可以将对象JSON.stringify() 编码后存储
sessionStorage
sessiongStorage
的三大特点:
- 生命周期为 当前浏览器窗口(标签页),关闭就结束
- 在当前页面(标签页)下可以使用数据
- 以键值对的形式存储使用
共有四个方法:
- 存储数据
sessionStorage.setItem(key, value)
- 获取数据
sessionStorage.getItem(key)
- 删除数据
sessionStorage.removeItem(key)
- 删除全部数据
sessionStorage.clear()
示例:
<body>
<input type="text">
<button class="set">存储数据</button>
<button class="get">获取数据</button>
<button class="remove">删除数据</button>
<button class="del">清空所有数据</button>
<script>
console.log(localStorage.getItem('username'));
var ipt = document.querySelector('input');
var set = document.querySelector('.set');
var get = document.querySelector('.get');
var remove = document.querySelector('.remove');
var del = document.querySelector('.del');
set.addEventListener('click', function() {
// 当我们点击了之后,就可以把表单里面的值存储起来
var val = ipt.value;
sessionStorage.setItem('uname', val);
sessionStorage.setItem('pwd', val);
});
get.addEventListener('click', function() {
// 当我们点击了之后,就可以把表单里面的值获取过来
console.log(sessionStorage.getItem('uname'));
});
remove.addEventListener('click', function() {
// 点击后,清楚指定key的数据
sessionStorage.removeItem('uname');
});
del.addEventListener('click', function() {
// 当我们点击了之后,清除所有的数据
sessionStorage.clear();
});
</script>
</body>
localStorage
localStorage
的三大特点:
- 生命周期为永久生效,关闭浏览器页面后也仍存在,除非手动删除
- 同一浏览器下,可以多窗口共享数据
- 以键值对的形式存储使用
它的使用方法和sessionStorage类似,共有四个方法:
- 存储数据
localStorage.setItem(key, value)
- 获取数据
localStorage.getItem(key)
- 删除数据
localStorage.removeItem(key)
- 删除全部数据
localStorage.clear()