页面加载事件
window.onload 是窗口(页面加载事件),当文档内容完全加载完成会触发该事件(包括图像、脚本文件、css文件等),就调用处理函数。
1.有了window.onload就可以把js代码写到元素页面的上方,因为onload是等页面内容全部加载完毕再去执行处理函数。
2.window.onload 传统注册事件只能写一次,如多有多个就会以最后一个window.onload为准。
3.如果使用addEventListener则没有限制。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> //---------传统注册事件-------------------------------- // window.onload = function (){ // var btn = document.querySelector('button'); // btn.addEventListener('click',function(){ // alert('123') // }) // } // window.onload = function(){ // alert(22) // } // --------------如果使用addEventListener则没有限制。------------------------ // 推荐 window.addEventListener('load', function () { var btn = document.querySelector('button'); btn.addEventListener('click', function () { alert('123') }) }) window.addEventListener('load', function () { alert(22) }) </script> <button>点击</button> </body> </html>DOMContentLoaded 事件触发时候,仅当DOM加载完成,不包括样式表、图片、flash等。ie9以上支持。
如果页面图片很多的话,从用户访问到onload触发可能需要较长的时间交互效果就不能实现,必然影响用户体验,此时用DOMContentLoaded 事件比较合适。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> // --------------如果使用addEventListener则没有限制。------------------------ // 推荐 window.addEventListener('load', function () { var btn = document.querySelector('button'); btn.addEventListener('click', function () { alert('123') }) }) window.addEventListener('load', function () { alert(22) }) // -------DOMContentLoaded ----------------- documen.addEventListener('DOMContentLoaded', function () { alert(33); }) </script> <button>点击</button> </body> </html>load是等页面内容全部加载完毕,包含dom元素 图片 flash css 等
DOMContentLoaded 是DOM加载完毕,不包含图片 flash css 等就可以执行 加载速度比load跟快一些。
window.onresize 是调整窗口大小加载事件,当触发时候就调用的处理函数
注意:
只要窗口大小发生改变,就会触发这个事件。
我们职场利用这个事件来完成响应式布局。window.innerWidth 当前屏幕的宽度。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> div { width: 100px; height: 100px; background-color: cornflowerblue; } </style> </head> <body> <div></div> <script> var div = window.document.querySelector('div'); window.addEventListener('resize', function () { console.log('变化了'); console.log(window.innerWidth); if (window.innerWidth <= 800) { div.style.display = 'none'; } else { div.style.display = 'block'; } }) </script> </body> </html>window对象提供了两种定时器
setTimeout()setInterval()只调用一次!!!
setTimeout() 方法用于设置一个定时器,该定时器到期后执行调用函数。
setTimeout() 这个函数我们也称为回调函数callback
普通函数是按照代码顺序直接调用。 而这个函数,需要等待时间,时间到了才调用这个函数。
element.onclick = function(){} 或者element.addEventListener(){‘click’,funcion(){}}; 里面的函数也是回调函数。
window.setTimeout(调用函数,[延迟毫秒数]); <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <!-- --> <script> // 这个window在调用时候可以shenglue // 这个延迟时间默认是毫秒,但是可以省略,如果省略默认是0 //第一种写法 setTimeout(function () { alert('已经两秒了') }, 2000) //第二种写法 // 这个调用函数可以直接写函数 还可以 写函数名 function boom() { alert('砰!') } setTimeout(boom, 3000) // 还有一种写法 不提倡 setTimeout('boom()', 4000) // 页面中可能有很多定时器,所以 最好给定时器加标识符(名字) var timer1 = setTimeout(boom, 5000) </script> </body> </html>停止setTimeout() 定时器
window.clearTimeout(timeoutID) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <button>停止定时器</button> <script> var btn = document.querySelector('button'); var timer = setTimeout(function () { console.log('砰') }, 3000) btn.addEventListener('click', function () { clearTimeout(timer) }) </script> </body> </html>可以一直循环调用!!!
window.setInterval(回调函数,[间隔的毫秒数]);setInterval() 方法重复调用一个函数,每隔这个事件就去调用一次回调函数。
注意:
window可以省略。这个回调函数可以直接写函数,或者写函数名或者采取字符串’函数名’ 三种形式。间隔毫秒数默认是0,如果写,必须是毫秒,标书每隔多少毫秒就自动调用这个函数。因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> setInterval(function(){ console.log('砰!'); },1000) </script> </body> </html>javaScript 最大的特点就是单线程,同一个事件只能做一件事情。
单线程意味着任务需要排队,会导致的问题:如果js执行时间过长,这样会造成渲染不连贯,导致加载阻塞的感觉。
window 对象给我们提供了一个location属性 用于获取或设置窗体的URL,并且可以用于解析URL。因为这个属性返回的是一个对象,所以我们将这个属性也称为location对象
统一资源定位符(url),是互联网上标准资源的地址。互联网上每个文件都有一个位置的url,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
https://www.bilibili.com/video/BV1k4411w7sV?p=93
login界面代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <form action="index.html"> 用户名:<input type="text" name="uname"> <input type="submit" value="登陆"> </form> </body> </html>index界面代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div></div> <script> console.log(location.search);// ?uname=1750306016 // 1.去掉? 用 substr('截取的起始位置','截取几个字符') var params = location.search.substr(1); console.log(params); // 2.利用 = 号 把字符串分割为数组 split('=') // 字符替换为数组 split('分隔符') 与join()把数组转化为字符串相反 // split('分隔符') 里面的分隔符取决于 字符串 里面用什么符号隔开 var arr = params.split('='); console.log(arr); // 把数据写入div中 var div = document.querySelector('div'); div.innerHTML = arr[1]+'你好'; </script> </body> </html> navigator 对象 包含有关浏览器的信息,它有很多属性,我们最常用的是userAgent,该属性可以返回由客户机发送服务器的 user-agent 头部的值。
下面的前端代码可以判断用户哪个终端打开页面:
代码演示视频
https://www.bilibili.com/video/BV1k4411w7sV?p=95
window 对象 给我们提供了一个history 对象,与浏览器记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL。
前进后退功能类似于下面按钮
var btn = document.querySelector('button'); btn.addEventListener('click',function(){ history.forward(); }) offset 翻译过来就是偏移量,我们使用 offset 系列相关属性可以动态的得到该元素的位置(偏移)、大小等。
获得元素距离带有定位父元素的位置。获得自身的大小(宽高)。注意:返回的数值都不带单位 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> body { margin: 0; padding: 0; } .father { /* 定位 */ position: relative; width: 100px; height: 100px; background-color: coral; margin: 100px; } .son { width: 50px; height: 50px; background-color: cornflowerblue; margin: 40px; } .w { width: 200px; height: 200px; background-color: rgb(76, 223, 142); margin: 0 auto 200px; padding: 20px; border: 2px solid #000; } </style> </head> <body> <div class="father"> <div class="son"></div> <div class="w"></div> </div> <script> var father = document.querySelector('.father') var son = document.querySelector('.son') var w = document.querySelector('.w') // 1.获得元素的偏移量 位置 返回不带单位的数值 console.log(father.offsetTop); console.log(father.offsetLeft); // 它以带有定位的父亲为准 如果没有父亲或者父亲没有定位 则以 body 为准 console.log(son.offsetLeft); // 2.可以得到元素的大小 宽度 和高度 是包含 padding + border + width console.log(w.offsetWidth); console.log(w.offsetHeight); // 3. 返回带有定位的父亲 否则返回的是body console.log(son.offsetParent); //返回父亲 返回的是最近一级的父亲 不管父亲有没有定位 console.log(son.parentNode); </script> </body> </html>有bug未解决 鼠标点击时候模态框会跳开
<style> .con { padding: 200px 0 0 200px; } .box { width: 300px; box-sizing: border-box; position: relative; } .box img { width: 100%; } .mask { display: none; position: absolute; width: 100px; height: 100px; top: 0; left: 0; background-color: yellow; opacity: .5; cursor: move; /* transform: translate(-50%, -50%); */ } .big { display: none; width: 600px; height: 600px; position: absolute; left: 550px; top: 200px; background-color: pink; border: solid 2px black; overflow: hidden; z-index: 999; } .big img { width: 1000px; display: block; position: absolute; top: 0; left: 0; } </style> <div class="con"> <div class="box"> <img src="/js进阶BOM/案例/timg.jpg" alt=""> <!-- 遮挡层 --> <div class="mask"></div> </div> <div class="big"> <img src="/js进阶BOM/案例/timg.jpg" alt="" class="bigimg"> </div> </div> <!-- 案例分析: 1、整个案例可以分为三个功能模块 2、鼠标经过小图片盒子,黄色的遮挡层和大图片盒子显示,离开隐藏两个盒子功能 3、黄色的遮挡层跟随鼠标功能 4、移动黄色遮挡层,大图片跟随移动功能 5、获得鼠标在盒子的坐标 6、把数值给遮挡层作为left和top值 7、此时用到鼠标移动事件,但是还是在小图片盒子内移动 8、遮挡层不能超出雄安盒子范围 9、如果小于0,就把坐标设置为0q 10、求大图片的移动距离公式 遮挡层/遮挡层最大移动距离 = 大图片移动距离/大图片最大移动距离 --> <script> window.addEventListener('load', function () { var box = document.querySelector('.box'); var mask = document.querySelector('.mask'); var big = document.querySelector('.big'); // 鼠标经过box时 大盒子 big 和遮挡层 mask 显示 box.addEventListener('mouseover', function () { mask.style.display = 'block'; big.style.display = 'block'; }) box.addEventListener('mouseout', function () { mask.style.display = 'none'; big.style.display = 'none'; }) box.addEventListener('mousemove', function (e) { // 先计算出鼠标在盒子内的坐标 var x = e.pageX - this.offsetLeft; var y = e.pageY - this.offsetTop; // 遮挡层mask距离盒子边框的距离 或者说mask 移动的距离 var maskX = x - mask.offsetWidth / 2; var maskY = y - mask.offsetHeight / 2; // 遮挡层最大移动距离 var maskMax = box.offsetWidth - mask.offsetWidth; var maskMaxY = box.offsetHeight - mask.offsetHeight; // 如果x坐标小于0,就让mask停在0的位置 if (maskX <= 0) { maskX = 0; } else if (maskX >= maskMax) { maskX = maskMax; } // Y坐标 if (maskY <= 0) { maskY = 0; } else if (maskY >= maskMaxY) { maskY = maskMaxY; } mask.style.left = maskX + 'px'; mask.style.top = maskY + 'px'; // 大图 var bigimg = document.querySelector('.bigimg'); // 大图可移动距离等于图片 - (大盒)容器宽度 var bigmax = bigimg.offsetWidth - big.offsetWidth; var bigmaxY = bigimg.offsetHeight - big.offsetHeight; console.log(bigimg.offsetWidth); console.log(bigmax); // 大图的移动距离,根据公式: 遮挡层/遮挡层最大移动距离 = 大图片移动距离/大图片最大移动距离 var bigX = maskX * bigmax / maskMax; var bigY = maskY * bigmaxY / maskMaxY; bigimg.style.left = -bigX + 'px'; bigimg.style.top = -bigY + 'px'; }) }) </script>我们使用client系列的相关属性来获取元素可视区的相关信息。通过client系列的相关属性可以得改元素的边框大小、元素大小等。
主要作用:创建一个独立作用域 避免命名冲突问题
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> // 立即执行函数:需要调用立马能够自己执行的函数。 // 两种写法 // (function(){})(); // // 或者 // (function(){}()); (function (a, b) { console.log(a); console.log(a + b); console.log(2); //第二个小括号可以看做是调用函数 里面可以添加实参 })(1, 3); // 如果有多个立即执行函数中间一定要用分号隔开 // 也可以给函数添加名字 (function sum(a, b) { console.log(a + b); }(2, 3)) // 立即执行函数最大的作用就是 独立创造了一个作用域 里面所有的变量都是局部变量 </script> </body> </html>scroll系列的相关属性可以动态的得到该元素的大小滚动距离
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> div{ width: 100px; height: 100px; background-color: brown; overflow: auto; } </style> </head> <body> <div> 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 </div> <script> var div = document.querySelector('div'); div.addEventListener('scroll',function(){ console.log(div.scrollLeft); }) </script> </body> </html>他们的主要用法:
1.offset系列经常用于获取元素位置 offsetLeft offsetTop
2.client经常用于获取元素大小 clientWidth clientHight
3.scroll经常用于获取滚动距离 scrollTop scrollLeft
4.注意页面的滚动距离通过window.pageXOffset 获得
核心原理:通过定时器()不断移动盒子位置。
实现步骤:
获得盒子当前的位置让盒子在当前位加上1和移动距离利用定时器不断重复这个动作加一个结束定时器的条件。注意元素需要添加定位,才能使用element.style.left注意函数需要传递的两个参数,动画对象和移动的距离。
如果多个元素都使用这个动画效果,每次都要声明一个定时器,我们可以给不同的元素使用不同的定时器(自己专门使用自己的定时器)。
核心原理:利用js是一门动态语言,可以很方便的给当前对象添加属性。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> div { position: absolute; left: 0; width: 200px; height: 200px; background-color: blueviolet; } span { position: absolute; left: 0; width: 100px; height: 100px; background-color: rgb(83, 155, 113); } button { margin-top: 300px; } </style> </head> <body> <div></div> <span></span> <button>点击方块移动</button> <!-- 动画原理 1. 获得盒子当前的位置 2. 让盒子在当前位加上1和移动距离 3. 利用定时器不断重复这个动作 4. 加一个结束定时器的条件。 5. 注意元素需要添加定位,才能使用element.style.left --> <script> // 简单动画函数的封装 obj目标函数 target目标对象 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'; }, 1) } var div = document.querySelector('div'); var span = document.querySelector('span') // 调用函数 var button = document.querySelector('button'); // 当我们不断点击了按钮,这个元素的速度会越来越快,因为开启了太多的定时器 // 解决方案就是让元素只有一个定时器执行 button.addEventListener('click', function () { animate(div, 200) animate(span, 600) }) </script> </body> </html>缓动动画就是让元素的运动速度有所变化。
思路:
让盒子每次移动的距离慢慢变小,速度就会慢慢落下来核心算法:(目标值 - 现在的值)/ 10 作为每次移动距离步长停止的条件是:让当前盒子位置等于目标位置就停止定时器步长值需要取整后退有点bug
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> div { position: absolute; left: 0; width: 200px; height: 200px; background-color: blueviolet; } span { position: absolute; left: 0; width: 100px; height: 100px; background-color: rgb(83, 155, 113); } button { margin-top: 300px; } </style> </head> <body> <div></div> <span></span> <button class="button600">点击方块移动600</button> <button class="button1000">点击方块移动1000</button> <script> // 简单动画函数的封装 obj目标函数 target目标对象 function animate(obj, target) { // 解决方案就是让元素只有一个定时器执行 // 先清除以前的定时器只保留一个定时器执行 clearInterval(obj.timer) //↓↓↓↓↓ 给不同元素指定了不同的定时器 obj.timer = setInterval(function () { // 步长值写到定时器里面 // 把步长值改为整数不要出现小数的距离 // var step = Math.ceil((target - obj.offsetLeft) / 10); // 判断div是前进还是后退 时候 步长值是向上取整还是向下取整 var step = (target - obj.offsetLeft) / 10; step = step > 0 ? Math.ceil(step) : Math.floor(step) if (obj.offsetLeft >= target) { // 停止动画本质是停止定时器 clearInterval(obj.timer) } // obj.style.left = obj.offsetLeft + step + 'px'; }, 15) } var div = document.querySelector('div'); var span = document.querySelector('span') // 调用函数 var btn600 = document.querySelector('.button600'); var btn1000 = document.querySelector('.button1000'); // 当我们不断点击了按钮,这个元素的速度会越来越快,因为开启了太多的定时器 // 解决方案就是让元素只有一个定时器执行 btn600.addEventListener('click', function () { animate(div, 200) }) btn1000.addEventListener('click', function () { animate(div, 600) }) </script> </body> </html> 回调函数原理:函数可以作为一个参数。将这个函数作为一个参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数,这个过程就叫做回调
回调函数写的位置:定时器结束的位置
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> div { position: absolute; left: 0; width: 200px; height: 200px; background-color: blueviolet; } button { margin-top: 300px; } </style> </head> <body> <div></div> <button class="button600">点击方块移动600</button> <button class="button1000">点击方块移动1000</button> <script> function animate(obj, target, callback) { clearInterval(obj.timer) obj.timer = setInterval(function () { 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(); } } // obj.style.left = obj.offsetLeft + step + 'px'; }, 15) } var div = document.querySelector('div'); var span = document.querySelector('span') // 调用函数 var btn600 = document.querySelector('.button600'); var btn1000 = document.querySelector('.button1000'); // 当我们不断点击了按钮,这个元素的速度会越来越快,因为开启了太多的定时器 // 解决方案就是让元素只有一个定时器执行 btn600.addEventListener('click', function () { // 回调函数 animate(div, 200, function () { div.style.backgroundColor = 'pink'; }) }) btn1000.addEventListener('click', function () { animate(div, 600) }) </script> </body> </html>独立新建一个js文件。
html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> div { position: absolute; left: 0; width: 200px; height: 200px; background-color: blueviolet; } </style> <script src="/js进阶BOM/js/animate.js"></script> </head> <body> <div></div> <script> var div = document.querySelector('div'); div.addEventListener('click', function () { animate(div, 400); }) </script> </body> </html>js文件
function animate(obj, target, callback) { clearInterval(obj.timer) obj.timer = setInterval(function () { 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(); } } // obj.style.left = obj.offsetLeft + step + 'px'; }, 15) }mouseenter鼠标事件
当鼠标移动到元素上时就会触发mouseenter事件类似于mouseover,他们两者之间的差别是mouseover 鼠标经过自身盒子会触发,经过子级盒子还会触发。mouseenter 只会经过自身盒子触发。之所以这样是因为mouseenter不会冒泡。跟mouseenter搭配的鼠标离开事件mouseleave同样不会冒泡独立新建一个js文件。
html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> div { position: absolute; left: 0; width: 200px; height: 200px; background-color: blueviolet; } </style> <script src="/js进阶BOM/js/animate.js"></script> </head> <body> <div></div> <script> var div = document.querySelector('div'); div.addEventListener('click', function () { animate(div, 400); }) </script> </body> </html>js文件
function animate(obj, target, callback) { clearInterval(obj.timer) obj.timer = setInterval(function () { 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(); } } // obj.style.left = obj.offsetLeft + step + 'px'; }, 15) }mouseenter鼠标事件
当鼠标移动到元素上时就会触发mouseenter事件类似于mouseover,他们两者之间的差别是mouseover 鼠标经过自身盒子会触发,经过子级盒子还会触发。mouseenter 只会经过自身盒子触发。之所以这样是因为mouseenter不会冒泡。跟mouseenter搭配的鼠标离开事件mouseleave同样不会冒泡