BOM:Browser Object Model
BOM: 专门操作浏览器窗口/软件的一套API
问题: 没有标准
何时: 希望操作浏览器窗口或读取浏览器软件的信息时
一.
1.包括:window: 2个角色:
1). 代替ES中的global充当全局作用域对象
2). 包含所有ES,DOM和BOM的API
又包括: history, location, document, navigator, screen, event
2.获取窗口大小:
1).2组:
*). 完整的窗口大小: window.outerWidth
window.outerHeight
*). 文档显示区大小: window.innerWidth
window.innerHeight
3.打开和关闭窗口:
1). 打开窗口: window.open()
4种:
*). 在当前窗口打开,可后退:
html:<a href="url" target="_self">
js: open("url", "_self");
*). 在当前窗口打开,禁止后退:
js: location.replace("url")
*). 在新窗口打开,可打开多个:
html:<a href="url" target="_blank">
js: open("url", "_blank");
*). 在新窗口打开,只能打开一个:
html: <a href="url" target="自定义窗口名">
js:
原理: 浏览器内存中,每个窗口都有一个唯一的窗口名
打开窗口时,也可通过target属性,为新窗口指定自定义的窗口名
浏览器规定同名的窗口只能打开一个。
后打开的同名窗口会自动将先打开的同名窗口覆盖掉
内置窗口名:
_self: 自动获取当前窗口自己的名字,作为新窗口的名字。
_blank: 不指定窗口名,在运行时,浏览器会自动随机分配窗口名。
关闭窗口: window.close()
4.history对象:
内存中保存当前窗口打开后,成功访问过的url的历史记录栈
每成功访问一个url,就会向history中push一个url记录
何时: 用程序模拟前进,后退或刷新时
如何: history.go(1) 前进一步
history.go(-1) 后退一步
history.go(-2) 后退两步
history.go(0) 刷新
5. location对象:
1).保存当前窗口正在打开的url的对象
2).属性: location.href 完整url
location.protocol 协议
location.host 主机名+端口号: 比如localhost:3000
location.hostname 主机名: 比如localhost
location.port 端口号: 3000
location.pathname 相对路径
location.hash #锚点地址
location.search ?查询字符串
3).方法:
*). 也可实现在当前窗口打开,可后退
location.assign("新url")和
location.href="新url"是一个意思俩种写法
location="新url"
几种方法都是一样的
*). 实现禁止后退:
location.replace("新url")
原理: 用新url替换history中旧的url
4). 刷新: 2种:
*). 普通刷新: 优先从浏览器本地缓存中获取资源。缓存中没有或过期,才去服务器下载新的。
F5
history.go(0)
location.reload()
*). 强制刷新: 跳过浏览器缓存,总是从服务器下载最新的资源
location.reload(true) true表示强迫
6.navigator对象:
保存浏览器配置信息的对象
1). 何时: 只要想获得浏览器的配置信息时
2).包括:
*). cookieEnabled: 判断当前浏览器是否启用了cookie
什么是cookie: 在客户端本地持久保存用户私密信息的小文件。
为什么: 程序中的数据,都是临时的。程序退出后,都释放。
何时: 只要希望程序关闭,数据也不丢失时
*). plugins: 保存浏览器安装的所有插件信息的集合
plugin: 插件,为浏览器提供新功能的小软件
*). userAgent: 保存浏览器名称(browser)和版本号(version)的字符串
何时: 只要判断浏览器的名称和版本号时
<!DOCTYPE HTML> <html> <head> <title>navigator对象常用属性</title> <meta charset="utf-8" /> </head> <body> <script> if(navigator.cookieEnabled==true){ document.write("<h1>已启用cookie,请妥善保存个人信息。</h1>") }else{ document.write("<h1>cookie已禁用,无法记住密码!</h1>") } //设置cookie: 打开Chrome右上角设置->高级->隐私...->内容管理->cookie->关闭第一项 if(navigator.plugins["Chrome PDF Plugin"]===undefined){ document.write(`<h1>未安装PDF插件,<a href="#">点此下载</a></h1>`) }else{ document.write(`<h1>已安装PDF插件!</h1>`) } //Edge浏览器 document.write(`<h1>${navigator.userAgent}</h1>`); var ua=navigator.userAgent; var browser, version; //如果ua中包含"Firefox" if(ua.indexOf("Firefox")!=-1){ browser="Firefox";//browser是Firefox }//否则如果ua中包含"IE",则browser是IE else if(ua.indexOf("IE")!=-1){ browser="IE"; }//否则如果ua中包含"Trident" else if(ua.indexOf("Trident")!=-1){ //则browser是IE,且version是11 browser="IE",version=11; }//否则如果ua中包含"OPR",则browser是OPR else if(ua.indexOf("OPR")!=-1){ browser="OPR"; }//否则如果ua中包含"Edge",则browser是Edge else if(ua.indexOf("Edge")!=-1){ browser="Edge"; }//否则如果ua中包含"Chrome",则browser是Chrome else if(ua.indexOf("Chrome")!=-1){ browser="Chrome"; }//否则如果ua中包含"Safari",则browser是Safari else if(ua.indexOf("Safari")!=-1){ browser="Safari"; } document.write(`<h1>${browser}</h1>`); if(version===undefined){ //获得浏览器名称第一个字符的位置 var i=ua.indexOf(browser); //跳过浏览器名称的长度再+1,到达版本号开始的位置 i=i+browser.length+1; //从版本号开始位置向后截取3位,转为数字 version=parseFloat(ua.slice(i,i+3)); } document.write(`<h1>${version}</h1>`); </script> </body> </html>
7. 事件:
什么是事件: 浏览器自动触发的或人为触发的页面内容状态的改变
什么是事件处理函数: 当事件发生时自动执行的函数
浏览器允许在事件发生之前,就提前为一个元素的事件属性绑定一个处理函数。
1).绑定
如何绑定事件:3种
*). 第一种:在HTML中: <ANY on事件名="js语句">
当事件发生时,自动执行提前规定的js语句
*).第二种: 在js中绑定: 赋值方式
elem.on事件名=function(){
//this->当前触发事件的.前的元素对象本身
}
问题: 一个事件属性,只能绑定一个处理函数
*). 第三种在js中绑定: 添加事件监听对象的方式:
elem.addEventListener("事件名",处理函数)
事件监听对象: 封装一组:事件名+元素+处理函数的组合的对象
浏览器中包含一个巨大的事件监听对象队列
每添加一个监听对象,都是加入到浏览器的监听对象队列中
如何查看事件监听对象:
F12->Elements->选中元素->Event Listener->展开click
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>...</title> </head> <body> <button id="btnShoot">shoot</button><br> <button id="btnAward">获得跟踪导弹</button><br> <button id="btnBreak">失去跟踪导弹</button><br> <script> var btnShoot= document.getElementById("btnShoot"); var btnAward= document.getElementById("btnAward"); var btnBreak= document.getElementById("btnBreak"); //单击btnShoot,发射普通子弹 btnShoot.addEventListener("click",function(){ console.log("发射普通子弹..."); }); function shoot2(){ alert("发射跟踪导弹=>=>=>"); } //当单击btnAward时 btnAward.onclick=function(){ //为btnShoot的单击事件再绑定第二种处理函数 btnShoot.addEventListener("click",shoot2) } //当单击btnBreak时 btnBreak.onclick=function(){ //从btnShoot上移除发射导弹的处理函数 btnShoot.removeEventListener( "click",shoot2 ) } </script> </body> </html>
*).移除监听对象:
elem.removeEventListener("事件名",原处理函数)
强调: 如果一个处理函数有可能被移除,则绑定时,就要用有名字的函数绑定。移除时才能使用函数名找到原处理函数。
[事件模型: 事件发生时到触发完所有处理函数的执行过程
事件流有两种:事件冒泡流、事件捕获流
事件冒泡流:具体触发事件的元素先接收事件,然后向上传导
事件捕获流:与冒泡流相反,最外层先接收到事件
所有浏览器的开发者认为,点在内层元素上,也等效于同时点在外层元素上。
点在d3同时触发d1.d2
三个阶段:
*). 事件捕获阶段: 由外向内依次记录各级父元素上的处理函数
只记录,不执行
(window -> document -> html -> body -> button注意:DOM2级规定从document开始,不包括事件目标,但是基本上浏览器都扩展到window层面,和事件目标层面)
*). 目标触发: 优先触发目标元素上的处理函数
目标元素: 最初点击的那个元素
*). 冒泡: 由内向外依次执行捕获阶段记录的各级父元素上的处理函数
(该阶段主要将事件目标绑定的结果返回给浏览器:button -> body -> html -> document -> window )
3).event对象:
什么是事件对象: 当事件发生时,自动创建的保存事件信息和API的对象
何时: 2种:
*). 如果要获得事件相关的信息时:
比如: 获得目标元素, 获得鼠标的位置
*). 如果希望改变事件的行为时:
比如: 阻止冒泡
如何:
*). 获得事件对象: 事件对象总是自动作为处理函数的第一个实参传入。
event对象
↓
elem.on事件名=function( e ){
}
API:
*). 取消冒泡: e.stopPropagation()
*). 利用冒泡:
优化: 尽量减少事件监听的个数
为什么: 因为浏览器触发事件时是采用遍历监听队列的方式找到符合条件的监听对象并执行处理函数。
监听对象的个数,就决定了遍历的速度。
如何: 当多个子元素需要绑定相同的事件时,其实只要在父元素上绑定一次即可。所有子元素通过冒泡共用!
两个难题:
*). 如何获得实际点击的目标元素:
this不行: this->父元素
e.target -> 目标元素
*). 鉴别目标元素是否想要的:
通过: class, 标签名, ......
<!DOCTYPE HTML> <html> <head> <title>取消与利用冒泡</title> <meta charset="utf-8"/> </head> <body> <div id="keys"> <button>1</button> <button>2</button> <button>3</button> <button>4</button><br> <button>C</button> <button>+</button> <button>-</button> <button>=</button> </div> <textarea id="sc" style="resize:none;width:200px; height:50px;" readonly></textarea> <script> var keys=document.getElementById("keys"); //查找用于显示的文本域元素 var sc=document.getElementById("sc"); keys.onclick=function(e){//e←event对象 var btn=e.target; //只有btn是button时,才执行后续任务 if(btn.nodeName=="BUTTON"){ alert(`我是 ${btn.innerHTML}`); switch(btn.innerHTML){//判断btn的内容 case "="://如果btn的内容是= //就获得sc的内容,放入eval()中计算,并将计算结果放回sc的内容中 try{ sc.value=eval(sc.value); }catch(err){ sc.value="Error"; } break; case "C"://否则如果btn的内容是C sc.value="";//就清空sc的内容 break; default://其余 sc.value+=btn.innerHTML;//就将btn的内容追加到sc的内容中 } } } </script> </body> </html>
阻止默认行为: e.preventDefault()
获得事件发生时,鼠标的位置:
事件坐标 3组:
*). 相对于显示屏左上角: e.screenX, e.screenY
*). 相对于文档显示区左上角: e.clientX, e.clientY
*). 相对于事件发生的元素左上角: e.offsetX, e.offsetY
<!doctype html> <html> <head> <meta charset="UTF-8"> <title>在当前显示区范围内实现点不到的小方块</title> <style> div{position:fixed;width:100px;height:100px; background-image:url(images/xiaoxin.gif); background-size:100%; } </style> </head> <body> <div id="pop"></div> <script> var pop=document.getElementById("pop"); //定义开关变量,用于控制图片是否跟随鼠标移动 var canMove=false; //定义变量在开始拖拽时,就保存鼠标距div左上角的相对位置 var offsetX,offsetY; //当在pop上按下鼠标时 pop.onmousedown=function(e){ canMove=true;//可以开始拖拽 //开始拖拽时,立刻获得鼠标距图片左上角的相对位置 offsetX=e.offsetX; offsetY=e.offsetY; } //当鼠标在窗口中移动时 window.onmousemove=function(e){ //只有当pop可以移动时 if(canMove==true){ //才让pop跟随鼠标移动 //求pop的top和left var left=e.clientX-offsetX; var top=e.clientY-offsetY; //设置pop的top和left属性: pop.style.left=left+"px"; pop.style.top=top+"px"; } } //当在pop上抬起鼠标按键时 pop.onmouseup=function(){ canMove=false;//停止拖拽 } </script> </body> </html>