3 BOM 3.1 概念 BOM是指浏览器对象模型 浏览器的对象模型提供了独立于内容的,可以与浏览器窗口进行互动的对象结构。 BOM由多个对象组成,其中代表浏览器窗口的Window对象是BOM的顶层对象,其他对象都是该对象的子对象
比如:刷新浏览器,后退,前进,在浏览器中输入URL等
window是浏览器的顶级对象,当调用window下的属性和方法时,可以省略window
我们定义的变量都是基于windows的
1 2 3 4 5 6 var abc="123" ;function fn ( ) { console .log("fn" ) } console .log(window .abc)window .fn();
注意:window下一个特殊的属性window.name无法被改变
window对象本身具有name和top两个属性,其中top属性是只读
3.2 对话框
alert() 弹出确定
prompt() 弹出是否
confirm() 弹出输入框
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 function ale ( ) { alert("提示信息!" ); } function firm ( ) { if (confirm("你确定提交吗?" )) { alert("点击了确定" ); } else { alert("点击了取消" ); } } function prom ( ) { var name = prompt("请输入您的名字" , "" ); if (name) { alert("欢迎您:" + name) } }
3.3 页面加载和关闭
页面加载完成后执行
onload
前面说过html是从上往下执行,如果把js写在hrad中,是获取不到页面中的元素的 不过加上页面加载后执行的方法就不一样了,可以吧js放到任意位置
页面加载完毕指的是:DOM元素加载完毕,并且外部文件加载完毕
1 2 3 4 5 onload = function ( ) { var box = document .getElementById("box" ); console .log("box" ) }
页面关闭时执行
onunload
1 2 3 onunload = function ( ) { console .log("再见" ) }
3.4 定时器
setTimeout()和clearTimeout() 在指定的行描述到到之后执行指定的函数,只执行一次
1 2 3 4 5 6 7 var timerId = setTimeout(function ( ) { console .log("Hello" ) },1000 ) clearTimeout(timerId);
setInterval()和clearInterval() 定时调用函数,可以按照给定的事件周期调用函数
1 2 3 4 5 6 7 var timerId = Interval(function ( ) { console .log("Hello" ) },1000 ) clearInterval(timerId);
案例:十秒后可以点击按钮
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 var btn = document .getElementById("btn" );var count = 10 ;var timerId = setInterval(function ( ) { count -- ; if (count > 0 ){ btn.value = "同意(请继续阅读" +count+"秒)" ; }else { btn.value = "同意" ; btn.disabled = false ; clearInterval(timerId); } },1000 )
5秒后跳转1 2 3 4 5 6 7 8 9 10 var timerId = setTimeout(function ( ) { location.href = "www.baidu.com" },5000 ); console .log(timerId);var btn = document .getElementById("btn" );btn.onclick = function ( ) { clearTimeout(timerId); }
定时器是典型的异步编程:在主线程还没有结束是不会调用其他线程的方法
3.5 内存中数据存储
栈内存中的变量一般都是已知大小或者有范围上限的,算作一种简单存储
堆内存存储的对象类型数据对于大小这方面,一般都是未知的
这也是为什么null作为一个object类型的变量却存储在栈内存中的原因。
一般来说栈内存线性有序存储,容量小,系统分配效率高。而堆内存首先要在堆内存新分配存储区域,之后又要把指针存储到栈内存中,效率相对就要低一些了。 垃圾回收方面,栈内存变量基本上用完就回收了,而推内存中的变量因为存在很多不确定的引用,只有当所有调用的变量全部销毁之后才能回收。
js中有四个基本类型的数据
他们的存储如图所示
其他类型,如对象数组存储如下图
const定义的基本类型不能改变,但是定义的对象是可以通过修改对象属性等方法来改变的。
3.6 移动div
.offsetLeft 左边距离
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var btn = document .getElementById("btn" );var box = document .getElementById("box" );btn.onclick = function ( ) { var timerId = setInterval(function ( ) { var current = box.offsetLeft; current +=8 ; if (current >=500 ){ clearInterval(timerId); box.style.left = "500px" ; return ; } box.style.left = current+"px" ; },30 ) }
3.7 location对象 location对象是window对象下的一个属性,使用的时候可以省略window对象
location可以获取或者设置浏览器地址的URL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 console .log(location) Location {replace : ƒ, assign : ƒ, href : "https://www.baidu.com/" , ancestorOrigins : DOMStringList, origin : "https://www.baidu.com" , …} ancestorOrigins: DOMStringList {length : 0 } assign: ƒ () hash: "" host: "www.baidu.com" hostname: "www.baidu.com" href: "https://www.baidu.com/" origin: "https://www.baidu.com" pathname: "/" port: "" protocol: "https:" reload: ƒ reload() replace: ƒ () search: "" toString: ƒ toString() valueOf: ƒ valueOf() Symbol (Symbol .toPrimitive): undefined __proto__: Location
location的几个方法
reload 重新加载
assign 跳转
replace 替换1 2 3 4 5 6 7 8 9 10 11 12 13 var btn = document .getElementById("btn" );btn.onclick = function ( ) { location.assign("http://www.baidu.com" ) location.replace("http://www.baidu.com" ) }
3.8 history对象
后退1 2 3 4 var btn = document .getElementById("btn" );btn.onclick = function ( ) { history.back(); }
前进1 2 3 4 var btn = document .getElementById("btn" );btn.onclick = function ( ) { history.forward(); }
3.9 navigator对象 Navigator 对象包含有关浏览器的信息。
userAgent 浏览器信息1 2 navigator.userAgent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"
在浏览器发送请求的时候会发送给服务器
如果调成手机模式会给服务器发送手机信息,服务器再判断是手机来源从而提供手机页面(在NGINX中有说明)
3.9 offsetWidth和offsetLeft
1 2 3 4 5 <body > <div id ="box1" > <div id ="box2" > </div > </div > </body >
1 2 3 4 5 6 7 8 9 10 11 12 var box2 = document .getElementById("box2" );console .log(box2.offsetWidth);console .log(box2.offsetHeight);console .log(box2.offsetLeft);console .log(box2.offsetTop);console .log(box2.offsetParent);console .log(box2.parentNode);
window相关宽高属性
window.outerHeight (窗口的外层的高度)
获取整个浏览器窗口的高度(单位:像素),包括侧边栏(如果存在)、窗口镶边(window chrome)和窗口调正边框。包含调试窗及浏览器边框
window.outerWidth (窗口的外层的宽度)
表示整个浏览器窗口的宽度,包括侧边栏(如果存在)、窗口镶边(window chrome)和调正窗口大小的边框。包含调试窗及浏览器边框
声明了显示当前浏览器的屏幕的宽度,以像素计
声明了显示当前浏览器的屏幕的高度,以像素计
offset
oEvent.clientX是指鼠标到可视区左边框的距离。 oEvent.clientY是指鼠标到可视区上边框的距离。
offsetWidth是指div的宽度(包括div的边框) offsetHeight是指div的高度(包括div的边框) offsetLeft是指div到整个页面左边框的距离(不包括div的边框) offsetTop是指div到整个页面上边框的距离(不包括div的边框)
scrollTop是指可视区顶部边框与整个页面上部边框的看不到的区域。 scrollLeft是指可视区左边边框与整个页面左边边框的看不到的区域。 scrollWidth是指左边看不到的区域加可视区加右边看不到的区域即整个页面的宽度(包括边框) scrollHeight是指上边看不到的区域加可视区加右边看不到的区域即整个页面的高度(包括边框)
clientWidth是指可视区的宽度。 clientHeight是指可视区的高度。 clientLeft获取左边框的宽度。 clientTop获取上边框的宽度。
3.11 案例 公共方法1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function getPage (e ) { return { pageX:e.clientX + getScroll().scrollLeft, pageY:e.clientY + getScroll().scrollTop } } function getScroll ( ) { return { scrollTop:document .documentElement.scrollTop || document .body.scrollTop, scrollLeft:document .documentElement.scrollLeft || document .body.scrollLeft, } }
拖拽弹出框
user-select:none CSS样式文本不能被选择
1 2 3 4 5 6 7 8 <div class ="nav" > <a href ="javascript:;" id ="register" > 注册信息</a > </div > <div class ="d-box" id ="d_box" > <div class ="hd" id ="drop" > 注册信息(可拖拽) <span id ="box_close" > 关闭</span > </div > </div >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 var d_box = document .getElementById("d_box" );var drop = document .getElementById("drop" );drop.onmousedown = function (e ) { e = e || event; var x = getPage(e).pageX - d_box.offsetLeft; var y = getPage(e).pageY - d_box.offsetTop; document .onmousemove = function (e ) { var boxX = getPage(e).pageX - x; var boxY = getPage(e).pageY - y; d_box.style.left = boxX + "px" ; d_box.style.top = boxY + 'px' ; } } document .onmouseup = function ( ) { document .onmousemove = null ; }
点击弹出拖拽登录框
window.innerWidth 页面的宽
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 var link = document .getElementById("link" );var login = document .getElementById("login" )link.onclick = function ( ) { var login = document .getElementById("login" ); var bg = document .getElementById("bg" ); } var title = document .getElementById("title" );title.onmousedown = function (e ) { e = e || event; var x = e.pageX - login.offsetLeft; var y = e.pageY - login.offsetTop; } document .onmousemove = function (e ) { e = e || event; var loginX = e.pageX - x; var loginY = e.pageY - y; if (loginX < 0 ){ loginX = 0 ; } if (loginY < 21 ){ loginY = 21 ; } if (loginX > window .innerWidth - login.offsetWidth - 21 ){ loginX = window .innerWidth - login.offsetWidth -21 ; } if (loginY > window .innerHeight - login.offsetHeigh){ loginY = window .innerHeight - login.offsetHeight; } login.style.left = loginX + 256 + "px" ; login.style.top = loginY - 140 + "px" ; } document .onmouseup = function ( ) { document .onmousemove = null ; }
放大镜
onmouseover和onmouseout 会有事件冒泡 onmouseenter和onmouseleave 不会触发冒泡
1 2 3 4 5 6 7 8 9 <div class ="box" id ="box" > <div class ="small" > <img src ="images/small.jpg" width ="350" alt ="" /> <div class ="mask" > </div > </div > <div class ="big" > <img src ="images/big.jpg" width ="800" alt ="" /> </div > </div >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 var box = document .getElementById("box" );var smallBox = box.children[0 ];var bigBox = box.children[1 ];var smallImg = smallBox.children[0 ];var mask = smallBox.children[1 ];var bigImg = bigBox.children[0 ];smallBox.onmouseover = function ( ) { mask.style.display = "block" ; bigBox.style.display = "block" ; } smallBox.onmouseout = function ( ) { mask.style.display = "none" ; bigBox.style.display = "none" ; } smallBox.onmousemove = function ( ) { e= e||event; var x = getPage(e).pageX - box.offsetLeft; var y = getPage(e).pageY - box.offsetTop; x -= mask.offsetWidth/2 ; y -+ mask.offsetHeight/2 ; x = x < 0 ? 0 : x; y = y < 0 ? 0 : y; var maxX = smallBox.offsetWidth - mask.offsetWidth; var maxY = smallBox.offsetHeight - mask.offsetHeight; x = x > maxX ? maxX : x; y = y > maxY ? maxY : y; mask.style.left = x + "px" ; mask.style.top = y + "px" ; var bigMaxX = bigImg.offsetWidth - bigBox.offsetWidth; var bigMaxY = bigImg.offsetWidth - bigBox.offsetHeight; var bigImgX = x * bigMaxX/maxX; var bigImgY = y * bigMaxY/maxY; bigImg.style.left = -bigImgX + "px" ; bigImg.style.top = -bigImgY + "px" ; }
模拟滚动条
1 2 3 4 5 6 7 8 <div class ="box" id ="box" > <div class ="content" id ="content" > 这里写文本信息 </div > <div class ="scroll" id ="scroll" > <div class ="bar" id ="bar" > </div > </div > </div >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 var box = document .getElementById("box" );var content = document .getElementById("content" );var scroll = document .getElementById("scroll" );var bar = document .getElementById("bar" );var barHeight = 0 ;if (content.scrollHeight > box.offsetHeight){ barHeight = box.offsetHeight / content.scrollHeight * scroll.offsetHeight; } bar.style.height = barHeight + "px" ; bar.onmousedown = function (e ) { e = e || event; var barY = getPage(e).pageY - bar.offsetTop - box.offsetTop; document .onmousemove = function (e ) { e= e || event; var y = getPage(e).pageY - barY - box.offsetTop; y = y < 0 ? 0 : y; var barMaxY = scroll.offsetHeight - barHeight; y = y > barMaxY ? barMaxY : y; bar.style.top = y + "px" ; var contentMaxY = content.scrollHeight - box.offsetHeight; var contentY = contentMaxY / barMaxY; content.style.top = - contentY + "px" ; } } document .onmouseup = function ( ) { document .onmousemove = null ; }
3.12 动画 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 var btn = document .getElementById("btn" );var timerId = null ;btn.onclick = function ( ) { var box = document .getElementById("box" ); var box1 = document .getElementById("box1" ); animate(box,function ( ) { animate(box1); }); } function animate (element,callback ) { if (element.timerId){ clearInterval(element.timerId); } element.timerId = setInterval(function ( ) { var target = 1000 ; var current = element.offsetLeft; var step = 10 ; if (current > target){ step = - Math .abs(step); } if (Math .abs(current - target) <= Math .abs(step)){ element.style.left = target + "px" ; clearInterval(element.timerId); return ; } if (callback){ callback() } current += step; element.style.left = current + "px" ; },20 ); }