DOM
1. DOM简介
1.1 什么是DOM
文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。 W3C 已经定义了一系列的 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式
1.2 DOM树
- 文档:一个页面就是一个文档,DOM 中使用 document 表示
- 元素:页面中的
所有标签 都是元素,DOM 中使用 element 表示 - 节点:网页中的
所有内容 都是节点(标签、属性、文本、注释等),DOM 中使用node 表示
DOM把以上内容都看成对象
2 获取元素
2.1 根据id获取
document.getElementById()
<body>
<div id="time">2022-2-26</div>
<script>
var timer = document.getElementById('time');
console.log(timer);
console.log(typeof timer);
console.dir(timer)
</script>
</body>
2.2 根据标签名获取
document.getElementsByTagName 例如获取所有的li标签元素
var list = document.getElementsByTagName('li');
如果要获取ul下面的li元素,可以
var olList = document.getElementsByTagName('ol');
var list2 = olList[0].getElementsByTagName('li');
2.3 通过 HTML5 新增的方法获取
- document.getElementsByClassName(‘类名’);// 根据类名返回元素对象集合
- document.querySelector(‘选择器’); // 根据指定选择器返回第一个元素对象
- document.querySelectorAll(‘选择器’); // 根据指定选择器返回
例如
<body>
<div class="box">盒子</div>
<div class="box">盒子</div>
<div id="nav">
<ul>
<li>首页</li>
<li>产品</li>
</ul>
</div>
<script>
document.getElementsByClassName('box');
document.querySelectorAll('.box');
document.querySelector('.box');
document.querySekector('#nav');
</script>
</body>
2.4 获取特殊元素(body,html)
- document.documentElement // 返回html元素对象
- doucumnet.body // 返回body元素对象
3 事件基础
3.1 事件三要素
- 事件源 (谁)
- 事件类型 (什么事件)
- 事件处理程序 (做啥)
<body>
<button id="btn">点我</button>
<script>
var btn = document.getElementById('btn');
btn.onclick = function() {
alert('点轻点');
}
</script>
</body>
3.2 常见的鼠标事件
4 操作元素
JavaScript 的 DOM 操作可以改变网页内容、结构和样式,我们可以利用 DOM 操作元素来改变元素里面的内容 、属性等。
4.1 改变元素内容
- element.innerText:读的时候去除html标签空格,只读文字,写的时候html标签当文字写
- element.innerHtml:读的时候不去除html标签空格,写的时候html标签格式写(推荐使用)
<body>
<div>
你好
<span>床前明月光</span>
</div>
<script>
var div = document.querySelector('div');
console.log(div.innerText);
div.innerText = "<strong>hello</strong>"
div.innerHTML = "<strong>hello</strong>";
console.log(div.innerHTML);
</script>
</body>
4.2 修改元素属性
常用元素的属性操作 src、href, id、alt、title
<body>
<button id="cat">猫</button>
<button id="dog">狗</button>
<img src="images/cat.jpg">
</body>
<script>
var cat = document.getElementById('cat');
var dog = document.getElementById('dog');
var imgSrc = document.querySelector('img');
cat.onclick = function() {
imgSrc.src = 'images/cat.jpg'
}
dog.onclick = function() {
imgSrc.src = 'images/dog.jpg'
}
</script>
4.3 表单元素的属性操作
可以通过dom操作如下元素
type、value、checked、selected、disabled
例子:实现密码隐藏显示效果
<style>
.box {
width: 400px;
border-bottom: 1px solid #ccc;
margin: 100px auto;
position: relative;
}
.box input {
width: 370px;
height: 30px;
border: none;
outline: none;
}
.box img {
width: 24px;
position: absolute;
top: 2px;
right: 2px;
}
</style>
<body>
<div class="box">
<label>
<img src="images/close.png" id="eye">
</label>
<input type="password" name="" id="password">
</div>
<script>
var eye = document.getElementById('eye');
var input = document.getElementById('password');
var flag = true;
eye.onclick = function() {
flag = !flag;
if(flag) {
eye.src = 'images/close.png';
input.type = 'password';
}else {
eye.src = 'images/open.png';
input.type = 'text';
}
}
</script>
</body>
4.4 样式属性操作
可以通过 JS 修改元素的大小、颜色、位置等样式。 如果样式修改比较少可以用 element.style ,如果修改样式比较多就用 element.className
4.4.1 element.style 行内样式操作
例子: 点击div时修改div背景色
<style>
div {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
<body>
<div></div>
<script>
var div = document.querySelector('div');
div.onclick = function() {
this.style.backgroundColor = 'purple';
}
</script>
</body>
注意: 1.JS 里面的样式采取驼峰命名法 比如 fontSize、 backgroundColor 2.JS 修改 style 样式操作,产生的是行内样式,CSS 权重比较高
4.4.1 element.className 类名样式操作
className 会直接更改元素的类名,会覆盖原先的类名。
<style>
.change {
height: 400px;
width: 400px;
margin: 100px auto;
background-color: pink;
}
</style>
<body>
<div>文本</div>
<script>
var div = document.querySelector('div');
div.onclick = function() {
this.className = 'change';
}
</script>
</body>
4.5 样式操作总结
4.6 自定义属性的操作
4.6.1 获取属性值
- element.属性 获取内置属性值(元素本身自带的属性)
- element.getAttribute(‘属性’); 主要获得自定义的属性 (标准) 程序员自定义的属性
<body>
<div id="box" index="1"></div>
<script>
var div = document.getElementById('box');
console.log(div.id);
console.log(div.getAttribute('index'));
</script>
</body>
4.6.2 设置属性值
- element.属性 设置内置属性值
- element.setAttribute(‘属性’); 主要设置自定义的属性 (标准)
4.6.3 移除属性
element.removeAttribute(‘属性’);
4.6.4 H5自定义属性
自定义属性获取是通过getAttribute(‘属性’) 获取。但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。 H5给我们新增了自定义属性:
-
设置H5自定义属性 H5规定自定义属性data-开头做为属性名并且赋值。 比如 <div data-index=“1”></div> 或者使用 JS 设置 element.setAttribute(‘data-index’, 2) -
获取H5自定义属性 -
兼容性获取 element.getAttribute(‘data-index’) ; -
H5新增 element.dataset.index , element.dataset[‘index’] ie 11才开始支持
5 节点操作
5.1 节点操作简介
5.1.1 为什么要学习节点操作
获取元素通常有两种方法 (1) 利用 DOM 提供的方法获取元素
- document.getElementById()
- document.getElementsByTagName()
- document.querySelector 等
- 逻辑性不强、繁琐
(2) 利用节点层级关系获取元素
- 利用父子兄节点关系获取元素
- 逻辑性强, 但是兼容性稍差
5.1.2 什么是节点
网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM 中,节点使用 node 来表示。HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以创建或删除。
利用 DOM 树可以把节点划分为不同的层级关系,常见的是父子兄层级关系
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个 基本属性。
- 元素节点 nodeType 为 1
- 属性节点 nodeType 为 2
- 文本节点 nodeType 为 3 (文本节点包含文字、空格、换行等)
我们在实际开发中,节点操作主要操作的是元素节点
5.2 获取节点
5.2.1 父节点
node.parentNode
- parentNode 属性可返回某节点的父节点,注意是最近的一个父节点
- 如果指定的节点没有父节点则返回 null
<body>
<div class="box">
<span>hello world</span>
</div>
<script>
var message = document.querySelector('span');
console.log(message.parentNode);
</script>
</body>
5.2.2 子节点
5.2.2.1 node.childNodes
注意:返回值里面包含了所有的子节点,包括元素节点,文本节点等。如果只想要获得里面的元素节点,则需要专门处理。 所以一般不提倡使用childNodes
<script>
var box = document.querySelector('.box');
var childNodes = box.childNodes;
for(let i = 0;i < childNodes.length; i++) {
if(childNodes[i].nodeType == 1) {
console.log(childNodes[i]);
}
}
</script>
5.2.2.2 parentNode.children(非标准)
parentNode.children 是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返 回 (这个是重点掌握的)。虽然children 是一个非标准,但是得到了各个浏览器的支持,因此可以放心使用
5.2.2.3 第一个和最后一个子节点
- parentNode.firstChild firstChild 返回第一个子节点,找不到则返回null。同样,也是包含所有的节点。
- parentNode.lastElementChild 返回最后一个子节点,找不到则返回null。同样,也是包含所有的节点。
5.2.2.4 第一个和最后一个子元素节点
- parentNode.firstElementChild 返回第一个子元素节点,找不到则返回null
- parentNode.lastChild 返回最后一个子元素节点,找不到则返回null
注意:这两个方法有兼容性问题,IE9 以上才支持。
实际开发中,firstChild 和 lastChild 包含其他节点,操作不方便,而 firstElementChild 和 lastElementChild 又有兼容性问题,那么如何获取第一个子元素节点或最后一个子元素节点呢? 解决方案:
- 如果想要第一个子元素节点,可以使用 parentNode.chilren[0]
- 如果想要最后一个子元素节点,可以使用 parentNode.chilren[parentNode.chilren.length - 1]
5.2.3 兄弟节点
5.2.3.1 兄弟节点
- node.nextSibling 返回当前元素的下一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点
- node.previousSibling 返回当前元素上一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点
5.2.3.2 兄弟元素节点
- node.nextElementSibling 返回当前元素下一个兄弟元素节点,找不到则返回null
- node.previousElementSibling 返回当前元素上一个兄弟节点,找不到则返回null
注意:这两个方法有兼容性问题, IE9 以上才支持
5.3 创建和添加节点
- document.createElement(‘tagName’) 创建节点
- node.appendChild(child) 将一个节点添加到指定父节点的子节点列表末尾
- node.insertBefore(child, 指定元素) 将一个节点添加到父节点的指定子节点前面
例子:
<body>
<ul>
<li>123</li>
</ul>
<script>
var ul = document.querySelector('ul');
var li = document.createElement('li');
ul.appendChild(li);
var li2 = document.createElement('li');
ul.insertBefore(li2, ul.children[0]);
</script>
</body>
5.4 删除节点
node.removeChild(child)
5.5 复制节点(克隆节点)
node.cloneNode()
- 如果括号参数为空或者为 false ,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
- 如果括号参数为 true ,则是深度拷贝,会复制节点本身以及里面所有的子节点
先克隆,再插入
6 DOM总结
6.1 创建
- document.write
- innerHTML
- createElement
6.2 增
6.3 删
6.4 改
主要修改dom的元素属性,dom元素的内容、属性, 表单的值等
- 修改元素属性: src、href、title等
- 修改普通元素内容: innerHTML 、innerText
- 修改表单元素:value、type、disabled等
- 修改元素样式: style、className
6.5 查
- DOM提供的API 方法: getElementById、getElementsByTagName 古老用法 不太推荐
- H5提供的新方法: querySelector、querySelectorAll 提倡
- 利用节点操作获取元素: 父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling) 提倡
6.6 属性操作
主要针对于自定义属性。
- setAttribute:设置dom的属性值
- getAttribute:得到dom的属性值
- removeAttribute移除属性
6.7 事件操作
事件高级
1 绑定和解绑事件
1.1 绑定事件
给元素添加事件,称为注册事件或者绑定事件。注册事件有两种方式:传统方式和方法监听注册方式
(1)传统注册方式: 利用 on 开头的事件 onclick 特点:注册事件唯一性,同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数 (2)addEventListener 方法监听注册方式: addEventListener() 方法 特点:同一个元素同一个事件可以注册多个监听器按注册顺序依次执行
方法和参数
eventTarget.addEventListener(type, listener, useCapture);
- type:事件类型字符串,比如 click 、mouseover ,注意这里不要带 on
- listener:事件处理函数,事件发生时,会调用该监听函数
- useCapture:可选参数,是一个布尔值,默认是 false。
btn.addEventListener('click', function() {
alert('hello world');
});
1.2 解绑事件
传统的监听解绑用eventTarget.onclick = null; , 方法监听注册方式用removeEventListener
eventTarget.removeEventListener(type, listener, useCapture)
<body>
<div>点我</div>
<div>点我</div>
<script>
var divList = document.getElementsByTagName('div');
divList[0].onclick = function() {
alert(111);
this.onclick = null;
}
divList[1].addEventListener('click', fun);
function fun() {
alert(222);
this.removeEventListener('click', fun);
}
</script>
</body>
1.3 DOM 事件流
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程 即 DOM 事件流。
比如我们给一个div 注册了点击事件,DOM 事件流分为3个阶段:
- 捕获阶段: 由 DOM 最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程
- 当前目标阶段
- 冒泡阶段 : 事件开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点的过程
注意:
- JS 代码中只能执行捕获或者冒泡其中的一个阶段
- onclick 和 attachEvent 只能得到冒泡阶段
- addEventListener第三个参数如果是 true,表示在事件捕获阶段。用事件处理程序;如果是 false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序
- 实际开发中我们很少使用事件捕获,我们更关注事件冒泡
- 有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave
- 事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件
下面是先son后father, 因为是冒泡的
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
var son = document.querySelector('.son');
var parent = son.parentElement;
son.addEventListener('click', function() {
alert('son');
});
parent.addEventListener('click', function() {
alert('father');
});
</script>
</body>
是先father后son, 因为是冒泡的
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
var son = document.querySelector('.son');
var parent = son.parentElement;
son.addEventListener('click', function() {
alert('son');
}, true);
parent.addEventListener('click', function() {
alert('father');
}, true);
</script>
</body>
2 事件对象
2.1 什么是事件对象
代码里的event 就是事件对象,我们还喜欢的写成 e 或者 evt
div.onclick = function(event) {
console.log(event);
}
div.addEventListener('click', function(event) {
console.log(event);
})
event 对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态
事件对象有兼容性问题,ie678通过windows.event, 兼容性写法:e = event || windows.event
2.2 事件对象的常见属性和方法
例如,阻止链接跳转
var a = document.querySelector('a');
a.addEventListener('click', function(e) {
e.preventDefault();
})
阻止链接冒泡 e.stopPropagation()
2.3 事件委托(代理、委派)
原理:不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点
<ul>
<li>知否知否,应是绿肥红瘦</li>
<li>知否知否,应是绿肥红瘦</li>
<li>知否知否,应是绿肥红瘦</li>
<li>知否知否,应是绿肥红瘦</li>
<li>知否知否,应是绿肥红瘦</li>
</ul>
如果要点击每个 li 都会弹出对话框,以前需要给每个 li 注册事件,是非常辛苦的,而且访问 DOM 的次数越多,这就会延长整个页面的交互就绪时间。利用事件委托可以给 ul 注册点击事件,然后利用事件对象的 target 来找到当前点击的 li,因为点击 li,事件会冒泡到 ul 上,ul 有注册事件,就会触发事件监听器
<script>
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
alert('知否知否,应是绿肥红瘦');
e.target.style.backgroundColor = 'pink';
})
</script>
2.4 常用的鼠标事件
2.4.1 基础鼠标事件
2.4.2 禁止鼠标选中文字和右键菜单
<script>
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
});
document.addEventListener('selectstart', function(e) {
e.preventDefault();
});
</script>
2.4.3 鼠标事件对象
event对象代表事件的状态,跟事件相关的一系列信息的集合。现阶段主要是用鼠标事件对象PointerEvent 和键盘事件对象 KeyboardEvent 。
2.4.3.1 e.target和this区别
e.target返回的是触发事件的对象, this返回的是绑定事件对象
<script>
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
console.log(e.target);
console.log(this);
})
</script>
2.4.3.2 鼠标事件对象属性
2.4.3.3 跟随鼠标的天使
<style>
img {
position: absolute;
}
</style>
<body>
<img src="images/angel.gif">
<script>
var img = document.querySelector('img');
document.addEventListener('mousemove', function(e) {
var x = e.pageX;
var y = e.pageY;
img.style.left = x - 50 + 'px';
img.style.top = y - 40 + 'px';
})
</script>
</body>
2.5 常用的键盘事件
2.5.1 常用的键盘事件
- keyup : 某个键盘弹起时
- keydown: 某个键盘按下时
- keypress: 非功能键按下时
三个键盘事件执行顺序是:keydown -- keypress --- keyup
<body>
<script>
document.addEventListener('keyup', function() {
console.log('键盘弹起');
});
document.addEventListener('keydown', function() {
console.log('键盘按下');
});
document.addEventListener('keypress', function() {
console.log('非功能键按下');
});
</script>
</body>
2.5.2 键盘事件对象
keyCode: 返回该键的ascall值
- keyup和keydown的keyCode不区分大小写,'a’和’A’都是65
- keypress的keyCode区分大小写,'a’是65, 'A’是97
- 在我们实际开发中,我们更多的使用keydown和keyup, 它能识别所有的键(包括功能键)
2.5.3 模拟京东按键输入内容
当按下 s 键, 光标就定位到搜索框
<body>
<div class="search">
<input placeholder="打印机">
<button>搜索</button>
</div>
<script>
var input = document.querySelector('input');
document.addEventListener('keyup', function(e) {
if(e.keyCode === 83) {
input.focus();
}
})
</script>
</body>
BOM
1 BOM概述
1.1 什么是DOM
BOM(Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是 window。
1.2 BOM 的构成
BOM 比 DOM 更大,它包含 DOM
1.3 BOM构成
window 对象是浏览器的顶级对象
- 它是 JS 访问浏览器窗口的一个接口。
- 它是一个全局对象。定义在全局作用域中的变量、函数都会变成 window 对象的属性和方法。在调用的时候可以省略 window,前面学习的对话框都属于 window 对象方法,如 alert()、prompt() 等。全局变量也是属于windows的变量
2 window 对象的常见事件
2.1 窗口加载事件
window.onload 是窗口 (页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS 文件等), 就调用的处理函数。
window.onload = function(){} 或者 window.addEventListener(“load”,function(){});
之前每次都是把js代码放在button后面,不然button还没加载js获不到节点会报错,通过window.onload 可以在页面加载完毕后执行js代码
<body>
<script>
window.addEventListener('load', function() {
var button = document.querySelector('button');
button.addEventListener('click', function() {
console.log(button);
});
})
</script>
<button>点我</button>
</body>
document.addEventListener(‘DOMContentLoaded’,function(){})
DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等
2.2 调整窗口大小事件
window.onresize 是调整窗口大小加载事件, 当触发时就调用的处理函数。
window.onresize = function(){} 或 window.addEventListener(“resize”,function(){});
- 只要窗口大小发生像素变化,就会触发这个事件
- 经常利用这个事件完成响应式布局。 window.innerWidth 当前屏幕的宽度
<body>
<script>
window.addEventListener('resize', function() {
console.log('改变屏幕大小');
})
</script>
</body>
3 定时器
window对象提供了两个定时器方法
- setTimeout() : 只执行一次
- setInterval() : 不断执行
3.1 setTimeout() 定时器
window.setTimeout(调用函数, [延迟的毫秒数]);
<script>
var timer = setTimeout(function() {
console.log('发起进攻')
}, 3000);
</script>
停止setTimeout定时器可以用 window.clearTimeout(timeoutID) ,其中timeoutId是setTimeout()的函数名,例如上述代码中的timer
3.2 setInterval() 定时器
第一次执行也是间隔毫秒数之后执行,之后每隔毫秒数就执行一次
window.setInterval(回调函数, [间隔的毫秒数]);
停止 setInterval() 定时器可以用 window.clearInterval(intervalID);
3.3 案例:手机验证码倒计时
<body>
<div class="box">
<input placeholder="请输入手机号" class="text">
<button class="btn">获取短信验证码</button>
</div>
<script>
var btn = document.querySelector('.btn');
var text = document.querySelector('.text');
btn.addEventListener('click', function(e) {
var value = text.value;
var second = 59;
if(value.length === 11) {
btn.disabled = true;
text.value = '';
text.placeholder = '请输入手机验证码';
var getNumber = setInterval(function() {
btn.innerHTML = '重发验证码(' + second + 's)';
second--
if(second < 1) {
clearInterval(getNumber);
text.value = value;
btn.disabled = false;
btn.innerHTML = '重发验证码';
}
}, 1000)
}
})
</script>
</body>
4 js同步和异步
HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程。于是,JS 中出现了同步和异步。 例如:下面代码输出 1, 2, 3
<script>
console.log(1);
setTimeout(function () {
console.log(3);
}, 1000);
console.log(2);
</script>
那下面代码呢? 结果还是1, 2, 3; 是不是有点意外呢?那是因为js的同步机制有点特别:分为同步任务和异步任务, 定时属于异步任务,而输出是同步任务,异步任务要等同步任务执行完再执行
<script>
console.log(1);
setTimeout(function () {
console.log(3);
}, 0);
console.log(2);
</script>
上述代码执行如下图,先执行主线程代码,再把消息队列中的代码拿到主线程去执行
5 window其他对象
5.1 location 对象
window 对象提供了一个 location 属性用于获取或设置窗体的 URL,并且可以用于解析 URL
5.2 navigator 对象
navigator 对象包含有关浏览器的信息,它有很多属性,我们最常用的是 userAgent,该属性可以返回由客 户机发送服务器的 user-agent 头部的值。 下面前端代码可以判断用户那个终端打开页面,实现跳转
5.3 history 对象
个 history 对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的 URL
- back() 后退
- forward() 前进
- go() 前进或后退,如果参数为1就前进1页, 如果为-2就后退2页
PC端网页特效
1 元素偏移量 offset 系列
1.1 offset概述
使用 offset 系列相关属性可以动态的得到该元素的位置(偏移)、大小等
- 获得元素距离带有定位父元素的位置, 如果父元素没有定位就返回距离body的距离
- 获得元素自身的大小(宽度高度)
1.2 offset使用
(1) 距离带有定位父元素的位置偏移
(2) 得到元素的大小(包含padding和margin)
(3) 得到带有定位的父亲 (没有就是body) offsetParent
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
var father = document.querySelector('.father');
var son = document.querySelector('.son')
console.log(father.offsetTop);
console.log(father.offsetLeft);
console.log(son.offsetLeft);
console.log(son.offsetTop);
console.log(son.offsetWidth);
console.log(son.offsetHeight);
console.log(son.offsetParent);
</script>
</body>
2 元素可视区 client 系列
2.1 常见属性
- clientTop: 返回元素上边框的大小
- clientLeft:返回元素左边框的大小
- clientWidth:返回元素宽度(不包含边框,包含内边距)
- clientHeight:返回元素高度(不包含边框,包含内边距)
2.2 立即执行函数
不需要调用,立马就能执行的函数,下面是立即执行函数的声明方法
(function() {})() 或者 (function(){}())
<body>
<script>
(function(a) {
console.log(a);
})(1);
(function(a){
console.log(a);
}(2));
</script>
</body>
3 元素滚动 scroll系列
3.1 scroll属性
- scrollTop:返回被卷去的上侧距离
- scrollLeft:返回被卷去的左侧距离
- scrollWidth:返回自身宽度(不带margin,带padding),与clientWidth不同的是, 当盒子不足放不下内容时,scrollWidth会返回内容宽度,而clientWidth只会返回盒子宽度
- scrollHeight:返回自身高度(不带margin,带padding),与clientHeight不同的是, 当盒子不足放不下内容时,scrollHeight会返回内容高度,而clientWidth只会返回盒子高度
3.2 案例:仿淘宝固定右侧侧边栏
- 页面被卷去的头部:可以通过window.pageYOffset 获得 如果是被卷去的左侧 window.pageXOffset
- 需要用到页面滚动事件 scroll 因为是页面滚动,所以事件源是 document
<body>
<div class="slider-bar">
<span class="goBack">返回顶部</span>
</div>
<div class="header w">头部区域</div>
<div class="banner w">banner区域</div>
<div class="main w">主体部分</div>
<script>
var sliderBar = document.querySelector('.slider-bar');
var banner = document.querySelector('.banner');
var bannerTop = banner.offsetTop;
var sliderBarTop = sliderBar.offsetTop - bannerTop;
var main = document.querySelector('.main');
var goBack = document.querySelector('.goBack');
var mainTop = main.offsetTop;
document.addEventListener('scroll', function() {
if(pageYOffset >= bannerTop) {
sliderBar.style.position = 'fixed';
sliderBar.style.top = sliderBarTop + 'px';
}else {
sliderBar.style.position = 'absolute';
sliderBar.style.top = '300px';
}
if(pageYOffset >= mainTop) {
goBack.style.display = 'block';
}else {
goBack.style.display = 'none';
}
})
</script>
</body>
<style>
.slider-bar {
position: absolute;
left: 50%;
top: 300px;
margin-left: 600px;
width: 45px;
height: 130px;
background-color: pink;
}
.w {
width: 1200px;
margin: 10px auto;
}
.header {
height: 150px;
background-color: purple;
}
.banner {
height: 250px;
background-color: skyblue;
}
.main {
height: 1000px;
background-color: yellowgreen;
}
span {
display: none;
position: absolute;
bottom: 0;
}
</style>
3.3 mouseenter 和mouseover的区别
- mouseover 鼠标经过自身盒子会触发,经过子盒子还会触发。 mouseenter 只会经过自身盒子触发
- 之所以这样,就是因为mouseenter不会冒泡
4 动画函数封装
4.1 原理
核心原理:通过定时器 setInterval() 不断移动盒子位置
实现步骤:
- 获得盒子当前位置
- 让盒子在当前位置加上1个移动距离
- 利用定时器不断重复这个操作
- 加一个结束定时器的条件
- 注意此元素需要添加定位,才能使用element.style.left
<body>
<div></div>
<script>
var div = document.querySelector('div');
var moveTimer = setInterval(function() {
if(div.offsetLeft >= 600) {
clearInterval(moveTimer);
}
div.style.left = div.offsetLeft + 1 + 'px';
}, 30);
</script>
</body>
4.2 动画函数封装
<body>
<button>点我才走</button>
<div>
</div>
<script>
function animate(obj, target) {
clearInterval(obj.timer);
obj.timer = setInterval(function() {
if(obj.offsetLeft >= target) {
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
}, 30);
}
var btn = document.querySelector('button');
var div = document.querySelector('div');
btn.addEventListener('click', function() {
animate(div, 600);
})
</script>
</body>
4.3 缓动效果
4.3.1 原理
- 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来。
- 核心算法: (目标值 - 现在的位置 ) / 10 做为每次移动的距离 步长
- 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
- 注意步长值需要取整
4.3.2 实现
<body>
<button>点我才走</button>
<div>
</div>
<script>
function animate(obj, target) {
clearInterval(obj.timer);
obj.timer = setInterval(function() {
var step = Math.ceil((target - obj.offsetLeft) / 10);
if(obj.offsetLeft === target) {
clearInterval(obj.timer);
}
obj.style.left = step + obj.offsetLeft + 'px';
}, 15);
}
var btn = document.querySelector('button');
var div = document.querySelector('div');
btn.addEventListener('click', function() {
animate(div, 600);
})
</script>
</body>
4.3.2 缓动动画添加回调函数
<body>
<button>点我才走</button>
<div>
</div>
<script>
function animate(obj, target, callback) {
clearInterval(obj.timer);
obj.timer = setInterval(function() {
var step = Math.ceil((target - obj.offsetLeft) / 10);
if(obj.offsetLeft === target) {
clearInterval(obj.timer);
if(callback) {
callback();
}
}
obj.style.left = step + obj.offsetLeft + 'px';
}, 15);
}
var btn = document.querySelector('button');
var div = document.querySelector('div');
btn.addEventListener('click', function() {
animate(div, 600, function() {
div.style.backgroundColor = 'red';
});
})
</script>
</body>
|