DOM
1 基本语句
获取元素:
getElementByld:获取带有ID的元素对象
getElementByTagName():获取某类标签元素
getElementsByClassName(‘类名’),根据类名获取某些元素集合
querySelector(‘选择器’) 根据指定选择器返回第一个元素对象,里面选择器需要加符号 .class,#id
querySelectorAll(‘选择器’)返回指定选择器的所有对象集合
document.body //返回body元素对象
document.documentElement //返回html元素对象
元素属性值:
获取元素属性值:
element.属性 获取内置属性值
element.getAttribute(‘属性’) 自己添加的自定义属性,兼容性获取
注:规定自定义对象 data-… ,dataset是一个集合里面存放了所有以data开头的自定义属性
H5新增、ie11开始支持:element.dataset**.index** 或者element.dataset**[‘index’]** ,它只能获取data-开头的
修改元素属性值
element.属性=‘值’
element.setAttribute(‘属性’,‘值’)
移除属性
removeAttribute(‘index’);
鼠标事件
鼠标事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过出发 |
onmouseout | 鼠标离开出发 |
onfocus | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点出发 |
onmousemove | 鼠标移动出发 |
mouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
mouseover和mouseenter
mouseenter鼠标事件
当鼠标移动到元素上时就会触发mouseenter事件
区别是:mouseover鼠标经过自身盒子会触发,经过子盒子还会触发。mouseenter只会经过自身盒子触发(子盒子不会触发(没有冒泡的概念))
mouseenter搭配鼠标离开mouseleave同样不会冒泡
操作元素
element.innerText:从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉
element.innerHTML:起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行
节点操作
利用父子兄节点关系获取元素,逻辑性强但兼容性较差
网页中所有内容都是节点(标签、属性、文本、注释等),在DOM中用node来表示。
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)、和nodeValue(结点值)这三个基本属性。
- 元素节点:nodeType为1,一般主要操作元素节点
- 属性节点:nodeType为2
- 文本节点:nodeType为3(文本节点包括文字、空格、换行等)
父节点:
node.parentNode:得到的是离元素最近的父节点,找不到父节点返回null
子节点:
parent.childNodes (标准)返回包含指定节点的子节点的集合,该集合为即时更新的集和。某一个就是.childNodes[i]
parent.children (非标准),但也得到各浏览器的支持
parentNode.firstChild返回第一个节点,不管是子节点还是元素节点,包括换行节点
parentNode.lastChild返回最后一个节点
parentNode.firstElementChild 返回第一个子元素节点,可能有兼容性问题
parentNode.lastElementChild返回最后一个子元素节点
实际开发中,没有兼容性的写法
xx.children[0]
xx.children[xx.children.length-1]
兄弟节点:
node.nextSibling:返回当前元素的下一个兄弟节点(包括换行),找不到则返回null
node.previousSibling:返回当前元素上一个兄弟节点(包括换行),找不到返回null
node.nextElementSibling:返回当前元素的下一个兄弟元素节点,ie9以上支持
node.previousElementSibling:返回当前元素的上一个兄弟元素节点,ie9以上支持
解决兼容性:自己封装函数
function getNextElementSibling(element){
var el = element;
while(el = el.nextSibling){
if(el.nodeType === 1){
return el;
}
}
return null;
}
创建(元素)节点:
document.createElement(‘tagName’)
创建由tagName指定的HTML元素,因为这些元素原来不存在,根据需求动态生成
添加节点:
node.appendChild(child) :node是父级,child是子级
将一个节点添加到指定父节点的子节点列表末尾,即后面追加元素。类似于css里面的after伪元素,数组里的push。
node.insertBefore(child,指定元素)
将一个节点添加到父节点的指定节点前面。类似于css里面before伪元素
ul.insertBefore(lili,ul.children[0]);//实现了在ul.children[0]前面插入子节点lili
删除节点:
node.removeChild(child)
返回删除的节点
ul.removeChild(ul.children[0])
复制节点(克隆节点):
node.cloneNode()返回调用该方法节点的一个副本。
括号参数:空或者false是浅拷贝,只克隆复制节点本身不复制里面的内容
true深拷贝,复制标签里面的内容。
ul.children[0].cloneNode(true)
三种创建元素的区别:
1、document.write():直接将内容写进页面的内容流,但是文档执行完毕,它会导致页面全部重绘。
document.write('<div>123</div>')
2、element.innerHTML:将内容写入某个DOM节点,不会导致页面全部重绘
var xx = document.querySelector('.xx');
xx.innerHTML = '<a herf='#'>百度</a>'
3、document.createElement() :创建多个元素,效率比innerHTML高,因为innerHTML采用拼接的方法
var xx = document.querySelector('.xx');
var a = document.createElement('a');
xx.appendChild(a);
注:innerHTML创建多个元素,如果采用数组形式拼接(push)效率更高,结构稍复杂
createElement()创建多个元素,直接拼接效率高,但是比innerHTML采用数组形式拼接效率低,但是结构更加清晰。
2. 操作实例
2.1 按钮点击变色
五个按钮,点击某个按钮,其背景颜色变为粉色,其他按钮颜色默认
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v8q0BogP-1650003500754)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220408141239164.png)]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
var btns = document.getElementsByTagName('button');
for(var i = 0;i < btns.length ; i++){
btns[i].onclick = function(){
for(var j = 0; j< btns.length;j++){
btns[j].style.backgroundColor = '';
}
this.style.backgroundColor = 'pink';
}
}
</script>
</body>
</html>
2.2 换肤效果
点击图片,页面背景改为当前的图片
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-33Ds5dB7-1650003500757)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220408110733486.png)]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin:0;
padding: 0;
}
body{
background: url(D:/image/img1.jpg) no-repeat center top;
}
li{
list-style: none;
}
.backChange{
overflow: hidden;
margin:100px auto;
background-color: aquamarine;
width: 410px;
padding-top: 3px;
}
.backChange li{
float: left;
margin: 0 1 px;
cursor: pointer;
}
.backChange img{
/* display:block; */
width: 100px;
margin-left: 1px;
/* height: 56.25px; */
}
</style>
</head>
<body>
<ul class="backChange">
<li><img src="D:\image\img1.jpg" alt=""></li>
<li><img src="D:\image\img2.jpg" alt=""></li>
<li><img src="D:\image\img3.jpg" alt=""></li>
<li><img src="D:\image\img5.jpg" alt=""></li>
<!-- <li><img src="D:\image\img5.jpg" alt=""></li> -->
</ul>
<script>
var imgs = document.querySelector('.backChange').querySelectorAll('img');
for(i = 0;i < imgs.length ;i++){
imgs[i].onclick = function(){
console.log(this.src);
document.body.style.backgroundImage='url('+this.src+')';
}
}
</script>
</body>
</html>
2.3 表格放置变色效果
鼠标经过一行变色,离开变回原色
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vfWK6Pgu-1650003500759)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220408113727117.png)]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
table{
width: 800px;
margin: 100px auto;
text-align: center;
border-collapse: collapse;
font-size: 14px;
}
thead tr{
height: 30px;
background-color: rgb(218, 114, 114);
}
tbody tr{
height: 30px;
}
tbody td{
border-bottom: 1px solid #999;
font-size: 12px;
color: rgb(255, 64, 0);
}
.bg{
background-color: rgb(241, 138, 101);
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th>姓名</th>
<th>班级</th>
<th>年龄</th>
<th>成绩</th>
<th>排名</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
</tbody>
</table>
<script>
var trs = document.querySelector('tbody').querySelectorAll('tr');
for(var i = 0;i<trs.length;i++){
trs[i].onmouseover = function(){
this.className='bg';
}
trs[i].onmouseout = function(){
this.className='';
}
}
</script>
</body>
</html>
2.4 表单全选与取消全选
要求一:全选按钮-所有选
要求二:单个按钮全部选-全选选中;单个按钮没有全部选-全选不选中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yBItS0I3-1650003500760)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220408144853661.png)]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
table{
width: 800px;
margin: 100px auto;
text-align: center;
border-collapse: collapse;
font-size: 14px;
}
thead tr{
height: 30px;
color: crimson;
background-color: rgb(253, 209, 209);
}
tbody tr{
height: 30px;
}
tbody td{
border-bottom: 1px solid #999;
font-size: 12px;
color: rgb(255, 64, 0);
}
</style>
</head>
<body>
<div class="wrap">
<table>
<thead>
<tr>
<th>
<input type="checkbox" name="" id="cbAll">
</th>
<th>商品</th>
<th>价格</th>
</tr>
</thead>
<tbody id="cb">
<tr>
<td>
<input type="checkbox" name="" id="">
</td>
<td>iPhone</td>
<td>10000</td>
</tr>
<tr>
<td><input type="checkbox" name="" id=""></td>
<td>ipad</td>
<td>5000</td>
</tr>
<tr>
<td><input type="checkbox" name="" id=""></td>
<td>apple</td>
<td>10</td>
</tr>
</tbody>
</table>
</div>
<script>
var cbAll =document.getElementById('cbAll');
var cb=document.getElementById('cb').getElementsByTagName('input');
//要求一:全选-所有选
cbAll.onclick=function(){
console.log(this.checked);
for(var i = 0 ; i < cb.length ; i++){
cb[i].checked = this.checked;
}
}
// 要求二:每一个都选了-全选;有一个没选-全选不选
for(var i = 0 ; i < cb.length ; i++){
cb[i].onclick = function(){
var flag = true;
for(var j = 0 ; j < cb.length ; j++){
if(!cb[j].checked){
flag = false;
break;
}
}
cbAll.checked = flag;
}
}
</script>
</body>
</html>
2.5 tab栏切换
①点击首行菜单栏,点一个其背景颜色变色,其余原色
②点的内容显示相应的详细信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wWe83Iss-1650003500760)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220408163546207.png)]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.tab_list li{
list-style: none;
float: left;
height: 39px;
line-height: 39px;
padding: 0 20px;
text-align: center;
cursor: pointer;
}
.tab_list .current{
background-color: rgb(224, 191, 191);
color: rgb(0, 0, 0);
}
/* .item_info{
padding: 20px 0 0 20px;
} */
.item{
display: none;
}
</style>
</head>
<body>
<div class="tab">
<div class="tab_list">
<ul>
<li class="current">商品介绍</li>
<li>规格包装</li>
<li>售后</li>
<li>商品评价</li>
<li>手机社区</li>
</ul>
</div>
<div class="tab_con">
<br><br>
<div class="item" style="display: block;">
商品模块介绍内容
</div>
<div class="item">
规格包装内容
</div>
<div class="item">
售后内容
</div>
<div class="item">
评价内容
</div>
<div class="item">
商品模块介绍内容
</div>
</div>
</div>
<script>
var tab_list = document.querySelector('.tab_list');
var lis = tab_list.querySelectorAll('li');
var items = document.querySelectorAll('.item');
for(var i=0 ; i<lis.length;i++){
lis[i].setAttribute('index',i);
lis[i].onclick = function(){
for(var j=0;j<lis.length;j++){
lis[j].className = '';
}
this.className = 'current';
var index = this.getAttribute('index');
console.log(index)
for(j = 0;j<items.length;j++){
items[j].style.display = 'none';
}
items[index].style.display = 'block';
}
}
</script>
</body>
</html>
2.6下拉菜单
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IGWd0gJ2-1650003500762)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220408200844472.png)]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>下拉菜单</title>
<style>
* {
margin: 0;
padding: 0;
}
li {
list-style-type: none;
}
a {
text-decoration: none;
font-size: 14px;
}
.nav {
margin: 100px;
}
.nav>li {
position: relative;
float: left;
width: 80px;
height: 41px;
text-align: center;
}
.nav li a {
display: block;
width: 100%;
height: 100%;
line-height: 41px;
color: #333;
}
.nav>li>a:hover{
background-color: rgb(240, 193, 133);
}
.nav ul{
display: none;
position:absolute;
top: 41px;
left: 0;
width: 100%;
border-left: 1px solid #FECC5B;
border-right: 1px solid #FECC5B;
}
.nav ul li{
border-bottom:1px solid #FECC5B;
}
.nav ul li a:hover {
background-color: #FFF5DA;
}
</style>
</head>
<body>
<ul class="nav">
<li>
<a href="#">微博</a>
<ul>
<li><a href="#">私信</a></li>
<li><a href="#">评论</a></li>
<li><a href="#">@我</a></li>
</ul>
</li>
<li>
<a href="#">微博</a>
<ul>
<li><a href="#">私信</a></li>
<li><a href="#">评论</a></li>
<li><a href="#"> @我</a></li>
</ul>
</li>
<li>
<a href="#">微博</a>
<ul>
<li><a href="#">私信</a></li>
<li><a href="#">评论</a></li>
<li><a href="#">@我</a></li>
</ul>
</li>
<li>
<a href="#">微博</a>
<ul>
<li><a href="#">私信</a></li>
<li><a href="#">评论</a></li>
<li><a href="#">@我</a></li>
</ul>
</li>
</ul>
<script>
var nav = document.querySelector('.nav');
var lis = nav.children;
for(var i=0;i<lis.length;i++){
lis[i].onmouseover = function(){
this.children[1].style.display = 'block';
}
lis[i].onmouseout = function(){
this.children[1].style.display='none';
}
}
</script>
</body>
</html>
2.7简单版发布留言
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lvE2QaPU-1650003500763)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220409094424855.png)]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
padding: 100px;
}
textarea {
width: 200px;
height: 100px;
border: 1px solid rgb(0, 73, 4);
outline: none;
resize: none;
}
ul {
margin-top: 50px;
}
li {
width: 300px;
padding: 5px;
background-color: rgb(248, 253, 179,0.5);
color: rgba(238, 144, 20, 0.76);
font-size: 14px;
margin: 15px 0;
}
</style>
</head>
<body>
<textarea name="" id=""></textarea>
<button>发布</button>
<ul>
<!-- <li>133</li> -->
</ul>
<script>
// 1. 获取元素
var btn = document.querySelector('button');
var text = document.querySelector('textarea');
var ul = document.querySelector('ul');
// 2. 注册事件
btn.onclick = function() {
if (text.value == '') {
alert('您没有输入内容');
return false;
} else {
// console.log(text.value);
// (1) 创建元素
var li = document.createElement('li');
// 先有li 才能赋值
li.innerHTML = text.value;
// (2) 添加元素
// ul.appendChild(li);
ul.insertBefore(li, ul.children[0]);
}
}
</script>
</body>
</html>
2.8 接2.7删除某些留言
<script>
// 1. 获取元素
var btn = document.querySelector('button');
var text = document.querySelector('textarea');
var ul = document.querySelector('ul');
// 2. 注册事件
btn.onclick = function() {
if (text.value == '') {
alert('您没有输入内容');
return false;
} else {
// console.log(text.value);
// (1) 创建元素
var li = document.createElement('li');
// 先有li 才能赋值
li.innerHTML = text.value + "<a href='javascript:;'>删除</a>";
// (2) 添加元素
// ul.appendChild(li);
ul.insertBefore(li, ul.children[0]);
//删除元素
var as = document.querySelectorAll('a');
for(var i = 0 ; i<as.length ; i++){
as[i].onclick=function(){
ul.removeChild(this.parentNode);
console.log(this.parentNode);
}
}
}
}
</script>
3 DOM重点核心
DOM(Document Object Model文档对象模型)是W3C组织推荐的处理可拓展标记语言(HTML或XML)的标准编程接口。
我们获取过来的DOm元素是一个对象(Object)所以称为文档对象模型
dom操作:创建、增、删、改、查、属性、事件
创建:document.write()
innerHTML
creatElement()
增:appendChild
insertBefore
删:removeChild()
改:修改dom元素属性、元素内容、表单
查:DOM提供的API方法:getElementById、getElementByTagName
H5提供的新方法:querySelector、querySelectorAll
利用节点获取元素:parentNode、Children、previousElementSibling、nextElementSibling
属性:setAttribute:设置属性值
getAttribute:得到属性值
removeAttribute:移除属性
事件:给元素注册事件:事件源.事件类型 = 事件处理程序
各鼠标事件
4 事件高级
4.1 注册事件(绑定事件)
两种方式:传统方式和方法监听注册方式
传统注册方式:特点注册事件的唯一性,同一个元素同一个事件只能设置一个处理函数,后面的会覆盖前面的处理函数
btn.onclick = funtion()
方法监听注册方式:addEventListener();IE9之前的IE不支持,可使用attachEvent()代替
4.1.1 addEventListener事件监听方式
同一个事件可以添加多个监听器
eventTarget.addEventListener(type, listener, useCapture)
btn.addEventListener('click', function(){
alert(22);})
btn.addEventListener('click', function(){
alert(33);})
type:事件类型,如click、mouseover,注意不带on,加引号
listener:事件处理函数,事件发生时调用该监听函数
useCapture:可选参数,布尔值,默认false
4.1.2 attachEvent事件监听方式
仅ie9以前的版本支持
eventTarget.attachEvent(eventNameWithOn , callback)
将指定的监听器注册到eventTarget(目标对象)上,对象触发指定事件后回掉函数被执行
eventNameWithOn:
callback:
btns[1].addEventListener('click', function() {
alert(33);})//attachEvent ie9以前的版本支持
4.2 删除事件(解绑事件)
4.2.1 传统方式
eventTarget.onclick = null;
divs[0].onclick = function() {
alert(11);
divs[0].onclick = null;
}
4.2.2 方法监听注册方式
① eventTarget.removeEventListener(type, listener, useCapture)
divs[1].addEventListener('click', fn) // 里面的fn 不需要调用加小括号
function fn() {
alert(22);
divs[1].removeEventListener('click', fn);
}
② eventTarget.detachEvent(eventNameWithOn , callback)
divs[2].attachEvent('onclick', fn1);
function fn1() {
alert(33);
divs[2].detachEvent('onclick', fn1);
}
4.3 DOM事件流
事件流描述的时从页面中接收事件的顺序。事件发生时会在元素节点之间按照特定的顺序传播,这个过程叫做DOM事件流。
document—html—body---------div--------body—html—document
DOM事件流分三个阶段:
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
①js代码只能执行捕获或冒泡其中一个阶段
②onclick和attachEvent只能得到冒泡阶段
③addEventListener(type, listener, useCapture),第三各参数如果是true则表示在捕获阶段调用事件处理程序。如果是false则是在冒泡阶段调用事件处理程序。
④实际更关注冒泡
⑤有些事件没有冒泡,如onblur,onfocus,onmouseenrter,onmouseleave
⑥事件冒泡有时会带来麻烦,有时会帮助
4.4 事件对象
4.4.1 概念和使用
var div = document.querySelector('div');
div.onclick = function(event){
}//event就是一个事件对象,当形参来看
事件对象只有有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数
事件对象代表事件的状态,比如鼠标按键的状态、鼠标的位置、鼠标按钮的状态
这个事件对象我们可以自己命名 比如 event 、 evt、 e
事件对象也有兼容性问题 :ie678 通过 window.event 兼容性的写法 e = e || window.event;
4.4.2 事件对象的属性和方法:
e.target:返回触发事件的对象(元素),this返回绑定事件的对象
区别 : e.target 点击了那个元素,就返回那个元素 this 那个元素绑定了这个点击事件,那么就返回谁
this有个非常相似的属性currentTarget ie6-8不认识
事件对象的属性方法 | 说明 |
---|---|
e.target | 返回出发事件的对象 标准 |
e.srcElement | 返回触发事件的对象 非标准ie6-8使用 |
e.type | 返回事件的类型 比如click、mouseover不带on |
e.cancelBubble | 该属性阻止冒泡,非标准ie6-8使用 |
e.returnValue | 该属性阻止默认事件(默认行为) 非标准ie6-8使用,比如不让链接跳转 |
e.preventDefault() | 该属性阻止默认事件(默认行为) 标准,比如不让链接跳转 |
e.stopPropagatiom() | 阻止冒泡 标准 |
4.5 阻止事件冒泡
e.stopPropagation(); // stop 停止 Propagation 传播
e.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡
var son = document.querySelector('.son');
son.addEventListener('click', function(e) {
alert('son');
e.stopPropagation(); // stop 停止 Propagation 传播
e.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡
}, false);
4.6 事件委托(代理、委派)
冒泡特性会带来好处
事件委托原理:不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
例如给ul注册事件,利用事件对象的target来找到当前来找到当前点击的li,事件会冒泡到ul上,ul有注册事件,就会触发事件监听器。
<ul>
<li>冒泡</li>
<li>冒泡</li>
<li>冒泡</li>
<li>冒泡</li>
</ul>
<script>
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e){
alert('冒泡泡');
e.target.style.backgroundColor = 'pink';
})
</script>
4.7 鼠标事件(其他)
[第一部分鼠标事件]:
4.7.1禁止鼠标右键菜单contextmenu
contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
document.addEventListener('contextmenu', function(e){
e.preventDefault();
})
4.7.2 禁止鼠标选中(selectstart开始选中)
document.addEventListener('selectstart',function(e){
e.preventDefault();
})
4.7.3 鼠标事件对象
鼠标事件对象MouseEvent,键盘事件对象KeyboardEvent
鼠标事件对象 | 说明 |
---|---|
e.clientX | 返回鼠标相对于浏览器窗口可视区的X坐标(滑动页面不影响) |
e.clientY | 返回鼠标相对于浏览器窗口可视区的Y坐标 |
e.pageX | 返回鼠标相对于文档页面的X坐标,IE9+支持(滑动页面改变) |
e.pageY | 返回鼠标相对于文档页面的Y坐标,IE9+支持 |
e.screenX | 返回鼠标相对于电脑频幕的X坐标 |
e.screenY | 返回鼠标相对于电脑频幕的Y坐标 |
4.7.4案例-跟随鼠标移动的图片
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
img{
position:absolute;
height: 15px;
}
</style>
</head>
<body>
<img src="D:\image\img4.jpg" alt="">
<script>
var pic = document.querySelector('img');
document.addEventListener('mousemove', function(e){
console.log(1);
var x = e.pageX + 10;
var y = e.pageY + 10;
pic.style.left = x + 'px';
pic.style.top = y + 'px';
})
</script>
</body>
</html>
4.8 键盘事件
4.8.1 基本事件
键盘事件 | 触发条件 |
---|---|
onkeyup | 某个键盘按键被松开时触发 |
onkeydown | 某个键盘按键被按下时触发 |
onkeypress | 某个键盘按键被按下时触发,但是不识别功能键如ctrl、shift、箭头等 |
<script>
// document.onkeyup = function(){
// console.log('弹起');
// }
document.addEventListener('keyup',function(){
console.log('keyup弹起');
})
document.addEventListener('keydown',function(){
console.log('keydown按下');
})
document.addEventListener('keypress',function(){
console.log('keypress按下');
})
</script>
注意keydown和keypress顺序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tj93dUrf-1650003500764)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220411155733001.png)]
4.8.2 keyCode属性
keyCode返回该键的ASCⅡ码值,从而判断用户按下了哪个键
keyup和keydown事件不区分字母大小写,a,A得到都是65
keypress区分大小写,a97,A65
4.8.3 案例-按键输入内容
按下键盘“s”,输入框被选中(焦点)
<body>
<input type="text" name="" id="">
<script>
var search = document.querySelector('input');
document.addEventListener('keyup',function(e){
if(e.keyCode===83){
search.focus();
}
})
</script>
</body>
4.8.4 案例-输入内容自动显示大字号的内容
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IbjGX1Wh-1650003500765)(C:\Users\Administrator\Pictures\image-20220411172915857.png)]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.search {
position: relative;
width: 100px;
margin: 50px;
}
.con {
display: none;
position: absolute;
top: -40px;
width: 171px;
border: 1px solid rgba(0, 0, 0, .2);
box-shadow: 0 2px 4px rgba(0, 0, 0, .2);
padding: 5px 0;
font-size: 20px;
line-height: 20px;
color: #333;
}
.con::before {
content: '';
width: 0;
height: 0;
position: absolute;
top: 28px;
left: 18px;
border: 8px solid #000;
border-style: solid dashed dashed;
border-color: #fff transparent transparent;
}
</style>
</head>
<body>
<div class="search">
<div class="con">空</div>
<input type="text" placeholder="请输入您的快递单号" class="input">
</div>
<script>
var con = document.querySelector('.con');
var input = document.querySelector('.input');
input.addEventListener('keyup',function(){
if(input.value == ''){
con.style.display = 'none';
}
else{
con.style.display = 'block';
con.innerHTML = this.value;
}
})
//失去焦点盒子隐藏
input.addEventListener('blur',function(){
con.style.display = 'none';
})
input.addEventListener('focus',function(){
if(this.value == ''){
con.style.display = 'none';
}
else{
con.style.display = 'block';
}
})
</script>
</body>
</html>
BOM
1 BOM概述
BOM浏览器对象模型(Browser Object Model),它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是window。
BOM缺乏标准,最初是Netscape浏览器标准的 一部分。JavaScript语法标准化组织是ECMA,DOM的标准化组织是W3C。
DOM | BOM |
---|---|
文档对象模型 | 浏览器对象模型 |
DOM就是把文档当作一个对象来看 | BOM就是把浏览器当作一个对象来看 |
DOM顶级对象是document | BOM顶级对象是window |
DOM是W3C标准规范 | BOM是浏览器厂商在各自浏览器上定义 的,兼容性较差 |
DOM主要学习的是操作页面元素 | BOM学习的是浏览器窗口交互的一些对象 |
window对象是浏览器的顶级对象,它具有双重角色
1、 它是JS访问浏览器窗口的一个接口
2、它是一个全局对象。定义在全局作用域中的变量、函数都会变成window对象的属性和方法
在调用的时候可以省略window
window下的一个特殊属性window.name,所以声明变量时不用name
2 window对象的常见事件
2.1窗口加载事件window.onload
window.onload = function(){
}
或者
window.addEventListener("load",function(){
});
当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS文件等)
注:有了window.onload就可以把JS代码写到页面元素的上方,因为onload是等页面全部加载完毕再去执行处理函数
window.onload传统注册事件方式只能写一次,如果有多个,会以最后一个window.onoad为准
如果使用addEventListener则没有限制
DOMContentLoaded事件:
DOMContentLoaded事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等
document.addEventListener('DOMContentLoaded',function(){
});
2.2 调整窗口大小事件window.onresize
window.onresize = function(){
}
window.addEventListener("resize",function(){
})
只要窗口大小发生像素变化,就会触发这个事件
常利用这个事件完成响应式布局。window.innerWidth当前屏幕的宽度
<body>
<script>
window.addEventListener('load',function(){
var div = document.querySelector('div');
window.addEventListener('resize',function(){
console.log(window.innerWidth);
console.log('窗口变化');
if(window.innerWidth <= 800){
div.style.display = 'none';
}else{
div.style.display = 'block';
}
})
})
</script>
<div></div>
</body>
3 定时器setTimeout()、setInterval()
3.1 setTimeout()
3.1.1使用
window.setTimeout(调用函数,[延迟的毫秒数]);//当设置的毫秒数到期后执行调用函数,这个window在调用时可省略
<script>
function callback(){
console.log('到时间了')
}
setTimeout(callback, 3000);
setTimeout('callback()', 3000);//不提倡这样的写法
</script>
页面中可能有很多定时器,我们经常给定时器加标识符
var timer1 = setTimeout(callback, 3000);
var timer1 = setTimeout(callback, 5000);
*回调函数:需要等待时间,时间到了才去调用这个函数,因此称回调函数
3.1.2 案例-五秒关闭广告
<body>
<img src="D:/image/img4.jpg" alt="" class="ad">
<script>
var ad = document.querySelector('.ad');
setTimeout(function(){
ad.style.display = 'none'
},5000)
</script>
</body>
3.1.3 clearTimeout()
clearTimeout()停止setTimeout()定时器
window.clearTimeout(timeoutID)
btn.addEventListener('click',function(){//给按钮添加结束定时器事件
clearTimeout(timer);
})
①window可以省略
②参数里的定时器标识符不需要引号
3.3setInterval()
3.3.1使用
window.setInterval(回调函数,[间隔的毫秒数])//重复调用一个函数(每隔xx秒调用这个回调函数)
setInterval(function(){
console.log('setInterval定时器');
},1000);
3.3.2 案例-倒计时
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sGBPcpIG-1650003500766)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220413111636203.png)]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>倒计时</title>
<style>
.countDown{
margin: 200px;
height: 50px;
width: 200px;
background-color: rgb(240, 176, 176);
}
span{
display: inline-block;
width: 50px;
height: 40px;
background-color: rgb(230, 241, 132);
text-align: center;
line-height: 40px;
margin: 5px;
}
.title{
background-color: rgba(144, 229, 255, 0.973);
position:absolute;
margin: -25px 200px;
color: burlywood;
}
</style>
</head>
<body>
<div class="title">倒计时:距离2022-4-15 10:00:00还有</div>
<div class="countDown">
<span class="hour">1</span>
<span class="minute">2</span>
<span class="second">3</span>
</div>
<script>
var hour = document.querySelector('.hour');
var minute = document.querySelector('.minute');
var second = document.querySelector('.second');
var inputTime = +new Date('2022-4-15 10:00:00');
countDown()//先调用一次这个函数,防止第一次刷新页面有空白
setInterval(countDown,1000);
function countDown(){
var nowTime = +new Date();//+new Date返回的是毫秒数,new Date返回标准时间
var times = (inputTime - nowTime) / 1000;
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>
</body>
</html>
3.3.1 clearInterval()
使用:
var stop = document.querySelector('.stop');
stop.addEventListener('click',function(){
clearInterval(timer);
})
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PTzzCJy7-1650003500766)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220413112258013.png)]
3.3.4 案例-发送短信案例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hHD8jfNz-1650003500767)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220413114316557.png)]
<body>
手机号码:<input type="number"><button>发送短信</button>
<script>
var btn = document.querySelector('button');
var time = 10 ;
btn.addEventListener('click',function(){
btn.disabled = true;
var timer = setInterval(function(){
if(time == 0){
clearInterval(timer);
btn.disabled = false;
btn.innerHTML = '发送短信';
time = 10;
}
else{
btn.innerHTML = '还剩下'+ time +'秒';
time--;
}
},1000)
});
</script>
</body>
4 JS执行机制
4.1 JS是单线程
JavaScript的一大特点就是单线程,即一个时间只能做一件事
4.2 同步和异步
为解决单线程一些问题,利用多核CPU的计算能力,HTML5提出了Web Worker标准,允许JavaScript脚本创建多个线程。于是有了同步和异步。本质区别是这条流水线上的各个流程执行顺序不同。
异步即等待时间内可以做其他任务
如下:执行输出为:1 2 3
console.log(1);
setTimeout(function() {
console.log(3);
}, 1000);
console.log(2);
定时器定时等待0秒也输出1 2 3
console.log(1);
setTimeout(function() {
console.log(3);
}, 0);//等待0s,但是依旧后运行
console.log(2);
4.3执行过程
同步任务:都在主线程上执行,形成一个执行栈
异步任务:JS异步是通过回调函数实现
- 普通事件:如click、resize等
- 资源加载:如load、errord等
- 定时器:包括setInterval、setTimeout等
执行过程:
- 先执行执行栈中的同步任务
- 异步任务(回调函数)放入任务队列中
- 执行栈中的同步任务执行完毕后,系统会一次读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈开始执行
事件循环:主线程不断重复获得任务、执行任务、再获取任务、再执行,这种机制被称作事件循环。
5 location对象
5.1 什么是location对象
window对象给我们提供了一个location属性用于获取或设置窗体的URL,并且可以用于解析URL。因为属性返回的是一个对象,所以称为location对象。
5.2 URL
统一资源定位符(Uniform Resource Locator),是互联网上标准资源的地址。互联网上每个文件都有唯一一个URL,它包含的信息指出文件位置以及浏览器应该怎么处理它。
语法格式:
protocol://host[:post]/path/[?query]#fragment
https://www.......
组成 | 说明 |
---|---|
protocol | 通信协议,常用的http,ftp,maito等 |
host | 主机(域名) |
port | 端口号,可选,省略时使用方案的默认端口,如http默认端口是80 |
path | 路径 由零或多个’/'符号隔开的字符串,一般用来表示主机上的一个目录或文件地址 |
query | 参数 以键值对的形式,通过&符号分隔开来 |
fragment | 片段 #后面内容 常见于链接 锚点 |
5.3 location对象的属性
location对象属性 | 返回值 |
---|---|
location.href | 获取或设置整个URL |
location.host | 返回主机(域名) |
location.port | 返回端口号 如果未写返回空字符串 |
location.pathname | 返回路径 |
location.search | 返回参数 |
location.hash | 返回片段 #后面内容 常见于链接 锚点 |
5.4 相关案例
5.4.1 5秒后跳转页面
<body>
<button>点击立即跳转</button>
<div></div>
<script>
var btn = document.querySelector('button');
var div = document.querySelector('div');
btn.addEventListener('click',function(){
location.href = 'http://www.baidu.com';
})
var timer = 5 ;
setInterval(function(){
if(timer == 0){
location.href = 'http://www.baidu.com'
}else{
div.innerHTML = '您将在'+timer+'秒后跳转页面'
timer--;
}
},1000);
</script>
</body>
5.4.2 获取URL参数数据
<body>
<form action="041304案例-index.html">
用户名:<input type="text" name="uname">
<input type="submit" value="登陆" name="" id="">
</form>
</body>
<body>
<div></div>
<script>
console.log(location.search);
var params = location.search.substr(1);//去掉?uname=ss里面的?
console.log(params);
var arr = params.split('=');//利用等号把字符串分割成数组
console.log(arr);
//把数据写入div中
var div = document.querySelector('div');
div.innerHTML = arr[1]+'欢迎';
</script>
</body>
5.5 location对象的方法
location对象的方法 | 返回值 |
---|---|
location.assign() | 与href一样,可以跳转页面(也称为重定向页面) |
location.replace() | 替换当前页面,因不记录历史,所以不能后退页面 |
location.reload() | 重新加载页面,相当于刷新按钮或者f5,如果参数为true强制刷新ctrl+5 |
6 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 = "";//手机
}
else{
window.location.href = "";//电脑
}
7 history对象
window对象提供了一个history对象,与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL。
history对象方法 | 作用 |
---|---|
back() | 可以后退功能 |
forward() | 前进功能 |
go(参数) | 前进后退功能,参数如果是1前进一个页面,如果是-1后退一个页面 |
<script>
var btn = document.querySelector('button');
btn.addEventListener('click',function(){
history.forward();
})
</script>
PC端网页特效
- offset
- client
- scroll
- 封装简单动画
- 网页轮播图
1 offset元素偏移量
1.1概述
使用offset系列相关属性可以动态得到该元素的位置(偏移)、大小等。
- 获得元素距离带有定位父元素的位置
- 获得元素自身的大小(宽度高度)
- 注意:返回的数值都不带单位
offset系列属性 | 作用 |
---|---|
element.offsetParent | 返回作为该元素带有定位的父级元素,如果父级都没有定位则返回body |
element.offsetTop | 返回元素相对带有定位父元素上方的偏移 |
element.offsetLeft | 返回元素相对带有定位父元素左边框的偏移 |
element.offsetWidth | 返回自身包括padding、边框、内容区的宽度,返回数值不带单位 |
element.offsetHeight | 返回自身包括padding、边框、内容区的高度,返回数值不带单位 |
1.2 offset与style的区别
offset | style |
---|---|
offset可以得到任意样式表中的样式值 | style只能得到行内样式表中的样式值 |
offset系列获得的数值是没有单位的 | style.width获得的是带单位的字符串 |
offsetWidth包含padding+border+width | style.width获得不包括padding和border的值 |
offsetWidth等属性是只读属性,只能获取不能赋值 | style.width是可读写属性,可以获取也可以赋值 |
结论:想要获取元素大小位置,用offset更合适 | 结论:想要给元素更改值,需要style改变 |
1.3 案例-获取鼠标在盒子内的坐标
利用鼠标在页面内的坐标pageX、pageY,盒子距离左和上的距离offsetLeft、offsetTop,求出鼠标在盒子里面的坐标
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box{
height: 300px;
width: 300px;
background-color: rgb(233, 201, 201,0.5);
margin: 30px;
text-align: center;
line-height: 200px;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
var box = document.querySelector('.box');
box.addEventListener('click',function(e){
console.log(e.pageX);
console.log(e.pageY);
console.log(box.offsetLeft);
console.log(box.offsetTop);
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
this.innerHTML = 'x坐标是'+x+'y坐标是'+y;
})
</script>
</body>
</html>
1.4 拖动模态框
点击链接,弹出登陆框,点关闭关闭登陆框,同时可以鼠标按下登陆会员位置,移动鼠标可以拖动登陆框。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.login-header{
width: 100%;
height: 30px;
text-align: center;
font-size: 30px;
}
a {
text-decoration: none;
color: #000000;
}
.login{
display: none;
width: 512px;
height: 250px;
position: fixed;
border: rgb(32, 237, 252) solid 2px;
left: 50%;
top: 40%;
background: #d4a9a9;
z-index: 9999;
transform: translate(-50%, -50%);
box-shadow: 0px 0px 20px #ddd;
}
.login-title{
width: 100%;
height: 40px;
margin: 10px 0 0 0;
text-align: center;
cursor: move;
font-size: 20px;
}
.close-login{
position: absolute;
border-radius: 50%;
text-align: center;
line-height: 40px;
right: -30px;
top: -30px;
background: rgba(0, 225, 255,0.3);
font-size: 14px;
width: 40px;
height: 40px;
border: rgba(122, 220, 250, 0.3) solid 1px;
}
.login-input-content {
margin-top: 20px;
}
.login-input {
overflow: hidden;
/* margin: 0px 0px 20px 0px; */
}
.login-input label {
margin: 0 0 0 15px;
float: left;
width: 90px;
padding-right: 10px;
text-align: right;
line-height: 35px;
height: 35px;
font-size: 18px;
}
.login-input .list-input {
float: left;
line-height: 35px;
height: 35px;
width: 350px;
border: #ffd903 1px solid;
text-indent: 5px;
}
.login-button {
width: 50%;
margin: 30px auto 0px auto;
line-height: 40px;
font-size: 14px;
border: #fa6c6c 1px solid;
text-align: center;
}
/* .login-button a {
display: block;
} */
.login-bg {
display: none;
width: 100%;
height: 100%;
position: fixed;
top: 0px;
left: 0px;
background: rgba(0, 0, 0, .3);
}
</style>
</head>
<body>
<div class="login-header"><a href="javascript:;" id="link">点击弹出登录框</a></div>
<div class="login" id="login">
<div class="login-title" id="title">登陆会员
<span><a class="close-login" id="closeBtn" href="Javacript:void(0);">关闭</a></span>
</div>
<div class="login-input-content">
<div class="login-input">
<label>用户名:</label>
<input type="text" placeholder="请输入用户名" name="info[username]" id="username" class="list-input">
</div>
<br>
<div class="login-input">
<label>登陆密码:</label>
<input type="password" placeholder="请输入登陆密码" name="info[password]" id="password" class="list-input">
</div>
</div>
<div id="loginBtn" class="login-button"><a href="javascript:void(0);" id="login-button-submit">登陆会员</a></div>
</div>
<!-- 遮盖层 -->
<div id="bg" class="login-bg"></div>
<script>
var login = document.querySelector('.login');
var mask = document.querySelector('.login-bg');
var link = document.querySelector('#link');
var closeBtn = document.querySelector('#closeBtn');
var title = document.querySelector('#title');
link.addEventListener('click',function(){
mask.style.display = 'block';
login.style.display = 'block';
});
closeBtn.addEventListener('click',function(){
mask.style.display = 'none';
login.style.display = 'none';
})
title.addEventListener('mousedown',function(e){
var x = e.pageX - login.offsetLeft;
var y = e.pageY - login.offsetTop;
document.addEventListener('mousemove',move);
function move(e){
login.style.left = e.pageX - x + 'px';
login.style.top = e.pageY - y + 'px';
}
document.addEventListener('mouseup',function(){
document.removeEventListener('mousemove',move);
})
})
</script>
</body>
</html>
2 client元素可视区
使用client系列相关属性来获取元素可视区的相关信息。动态得到元素边框大小、元素大小
client 宽度 和我们offsetWidth 最大的区别就是 不包含边框
client系列属性 | 作用 |
---|---|
element.clientTop | 返回元素上边框大小 |
element.clientLeft | 返回元素左边框大小 |
element.clientWidth | 返回自身包括padding、内容区宽度,不含边框,返回数值不带单位 |
element.clientHeight | 返回自身包括padding、内容区高度,不含边框,返回数值不带单位 |
2.1 立即执行函数
立即执行函数,不需要调用,立马能够自己执行的函数。
立即执行函数最大的作用就是 独立创建了一个作用域, 里面所有的变量都是局部变量 不会有命名冲突的情况。
(function(){})()
//或者
(function(){}());
(function(a,b){
console.log(a + b);
})(1,2);//两个立即执行函数前一个最后一定要有分号
(function(a,b){
console.log(a+b);
}(2,3));
2.2 物理像素比dpr
pc端物理像素比为1,一些移动端如iphone678,dpr为2
var dpr = window.devicePixelRatio || 1
2.3 pageshow
页面发生变化时,重新设置。
load事件触发:a标签超链接、F5或刷新按钮(强制刷新)、前进后退按钮
一些浏览器如火狐,特点往返缓存,村村中保存着页面数据、DOM和JavaScript状态,实际上是整个页面都保存在内存里。所以,此时后退按钮不会刷新页面。
pageshow事件在页面显示时触发,无论页面是否来自缓存。在重新加载页面中,pageshow会在load事件触发后触发;根据事件对象中的persisted来判断是否是缓存中的页面触发的pageshow事件。
注意:这个事件给window添加。
window.addEventListener('pageshow',function(e){
//e.persisted返回的true就是从缓存取出来的页面
alert('11');
})
window.addEventListener('load',function(){
alert('11');
})
3 元素滚动scroll
动态得到元素大小、滚动距离等。(内容大小,如盒子内文字超出盒子范围,返回内容的实际属性)
scroll系列属性 | 作用 |
---|---|
element.scrollTop | 返回被卷上去的上侧距离,返回数值不带单位 |
element.scrollLeft | 返回被卷上去的左侧距离,返回数值不带单位 |
element.scrollWidth | 返回自身的实际宽度,不含边框,返回数值不带单位 |
element.scrollHeight | 返回自身的实际高度,不含边框,返回数值不带单位 |
3.1 onscroll事件
页面被卷去的头部,滚动条向下滚动,页面上被隐藏的高度,称页面被卷去的头部。滚动条在滚动时会触发onscroll事件。
div.addEventListener('scroll',function(){
console.log(div.scrollTop)
})
3.2 案例-侧边栏定位
页面滚动到一定位置,出现返回顶部操作
*页面被卷去的头部:可以通过window.pageYOffset获得,被卷去的左侧window.pageXOffset
*元素被卷去的头部element.scrollTop
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<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: rgb(231, 203, 231);
}
.banner {
height: 250px;
background-color: rgb(198, 236, 252);
}
.main {
height: 1000px;
background-color: rgb(211, 223, 188);
}
span {
display: none;
position: absolute;
bottom: 0;
}
</style>
</head>
<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 main = document.querySelector('.main');
var goBack = document.querySelector('.goBack');
var sliderbarTop = sliderbar.offsetTop - banner.offsetTop;
document.addEventListener('scroll',function(){
if(window.pageYOffset > banner.offsetTop){
sliderbar.style.position = 'fixed';
sliderbar.style.top = sliderbarTop + 'px';
}
else{
sliderbar.style.position = 'absolute';
sliderbar.style.top = '300px';
}
if(window.pageYOffset > main.offsetTop){
goBack.style.display = 'block';
}
else{
goBack.style.display = 'none';
}
})
</script>
</body>
</html>
3.3 页面被卷去的头部兼容性解决方法
因为兼容性问题,所以被卷去的头部通常有如下几种写法:
- 声明了DTD,使用document.documentElement.scrollTop
- 未声明DTD,使用document.body.scrollTop
- 新方法window.pageYOffset和window.pageXOffset,ie9开始支持
function getScroll(){
return{
left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0 ,
top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
};
}
//使用
getScroll().left
3.4 三大系列总结
- offset系列用于获得元素位置 offsetLeft、offsetTop
- client常用于获取元素大小clientWidth、clientHeight
- scroll常用于获得滚动距离scrollTop、scrollLeft
- 注意页面滚动的距离通过window.pageXOffset获得
4 动画函数封装
4.1动画实现原理
核心原理:定时器setInterval()不断移动盒子位置。
- 获得盒子当前位置
- 让盒子在当前位置加上1个移动距离
- 利用定时器不断重复这个操作
- 加一个结束定时器的条件
- 注意此元素需要添加定位, 才能使用element.style.left
<script>
//动画元素需要添加定位position
var div = document.querySelector('div');
var timer = setInterval(function(){
if(div.offsetLeft > 400){
clearInterval(timer)
}
div.style.left = div.offsetLeft + 5 +'px';
},30);
</script>
4.2 动画函数封装
需要传递两个参数:动画对象和移动的距离
<button>点击开始小方块</button>
<div></div>
<span></span>
<script>
//动画元素需要添加定位position
var div = document.querySelector('div');
var span = document.querySelector('span');
var btn = document.querySelector('button');
animate(div,300);
btn.addEventListener('click',function(){
animate(span,200);
})
function animate(obj, target){
// 当我们不断的点击按钮,这个元素的速度会越来越快,因为开启了太多的定时器
// 解决方案就是 让我们元素只有一个定时器执行
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function(){
if(obj.offsetLeft > target){
clearInterval(obj.timer)
}
obj.style.left = obj.offsetLeft + 5 +'px';
},30);
}
</script>
4.3 缓动动画
缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来
- 让盒子每次移动的距离慢慢变小,速度慢慢落下来
- 核心算法:(目标值-现在位置)/10 作为每次移动的步长
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 = obj.offsetLeft + step +'px';
},15);
}
若添加回掉函数,回调函数写在定时器结束里面
4.4 实例-缓动动画
鼠标移动到箭头位置,展开问题反馈盒子
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RP3qkNDB-1650003500769)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220415103855591.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AZjfIYfG-1650003500769)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220415103810021.png)]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.sliderbar {
position: fixed;
right: 0;
bottom: 100px;
width: 40px;
height: 40px;
text-align: center;
line-height: 40px;
cursor: pointer;
color: rgb(248, 116, 116);
}
.con {
position: absolute;
left: 0;
top: 0;
width: 200px;
height: 40px;
background-color: rgb(240, 193, 240);
z-index: -1;
}
</style>
<script src="animate.js"></script>
</head>
<body>
<div class="sliderbar">
<span>←</span>
<div class="con">问题反馈</div>
</div>
<script>
var sliderbar = document.querySelector('.sliderbar');
var con = document.querySelector('.con');
sliderbar.addEventListener('mouseenter',function(){
animate(con,-160,function(){
sliderbar.children[0].innerHTML = '→';
});
})
sliderbar.addEventListener('mouseleave',function(){
animate(con,0,function(){
sliderbar.children[0].innerHTML = '←';
});
})
</script>
</body>
</html>
5 常见网页特效案例
j.timer)
}
obj.style.left = obj.offsetLeft + 5 +‘px’;
},30);
}
#### 4.3 缓动动画
缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来
1. 让盒子每次移动的距离慢慢变小,速度慢慢落下来
2. 核心算法:(目标值-现在位置)/10 作为每次移动的步长
```javascript
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 = obj.offsetLeft + step +'px';
},15);
}
若添加回掉函数,回调函数写在定时器结束里面
4.4 实例-缓动动画
鼠标移动到箭头位置,展开问题反馈盒子
[外链图片转存中…(img-RP3qkNDB-1650003500769)]
[外链图片转存中…(img-AZjfIYfG-1650003500769)]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.sliderbar {
position: fixed;
right: 0;
bottom: 100px;
width: 40px;
height: 40px;
text-align: center;
line-height: 40px;
cursor: pointer;
color: rgb(248, 116, 116);
}
.con {
position: absolute;
left: 0;
top: 0;
width: 200px;
height: 40px;
background-color: rgb(240, 193, 240);
z-index: -1;
}
</style>
<script src="animate.js"></script>
</head>
<body>
<div class="sliderbar">
<span>←</span>
<div class="con">问题反馈</div>
</div>
<script>
var sliderbar = document.querySelector('.sliderbar');
var con = document.querySelector('.con');
sliderbar.addEventListener('mouseenter',function(){
animate(con,-160,function(){
sliderbar.children[0].innerHTML = '→';
});
})
sliderbar.addEventListener('mouseleave',function(){
animate(con,0,function(){
sliderbar.children[0].innerHTML = '←';
});
})
</script>
</body>
</html>