BOM
Browser Object Model 浏览器对象模型
全局对象
window
每打开一个浏览器就会创建一个全局对象(window)
全局变量为全局对象的属性,全局函数为全局对象的方法 (window.变量名) 注:ES5声明
以ES6形式声明的方法和变量无法加入全局对象,而以ES5形式声明的全局变量和函数(包括函数表达式创建的函数、箭头函数)会成为全局对象的属性和方法,可以正常访问,但无法被删除。只能删除以全局对象新增或已存在的键名。
以字面量(函数声明式)方式声明的函数,全局对象是可以正常访问和调用的。
let i = 10;
console.log(window.i);//undefined
var j = 23;
console.log(window.j);//23
//无法删除以ES5声明形式创建的全局变量的键名
delete window.j;
console.log(window.j);//23
//可以删除以全局对象新增或已存在的键名
window.k = "hello";
console.log(window.k);//hello
delete window.k;
console.log(window.k);//undefined
var myFunction = function () {
console.log("hello");
}
window.myFunction();// hello (let 形式创建的不可以访问 会返回window.myFunction is not a function)
function myFunction1() {
console.log("hello world");
}
window.myFunction1();// hello world
var myFunction2 = () => {
console.log("hahahahahahha");
}
window.myFunction2();//hahahahahahha
let myFunction3 = function () {
console.log("adka");
}
console.log(window.myFunction3);//undefined
windows的属性
获取浏览器与屏幕的距离
离屏幕左侧的距离
-
screenLeft不支持Firefox -
screenX不支持IE8以下
console.log(window.screenLeft);//不支持Firefox
console.log(window.screenX);//不支持IE8以下
离屏幕上端的距离
screenTop不支持FirefoxscreenY不支持IE8以下
console.log(window.screenTop); //不支持Firefox
console.log(window.screenY);//不支持IE8以下
获取浏览器的尺寸(不带单位)
视口尺寸
不包含控制台、地址栏、标签页、菜单等、以及被放置在视口之外的元素
innerWidth视口(viewport)的宽度innerHeight视口(viewport)的高度
console.log(window.innerWidth);//视口(viewport)的宽度
console.log(window.innerHeight);//视口(viewport)的高度
浏览器整体尺寸
包含控制台、地址栏、标签页、菜单等、以及被放置在视口之外的元素
outerWidth浏览器的宽outerHeight浏览器的高
console.log(window.outerWidth);
console.log(window.outerHeight);
获取浏览器的滚动条尺寸
pageXOffset/srollX滚动条水平方向上的尺寸pageYOffset/srollY滚动条方向上的尺寸
//获取浏览器的滚动条尺寸
console.log(`x轴:` + window.pageXOffset);
console.log(`y轴:` + window.pageYOffset);
console.log(`x轴:` + window.scrollX);
console.log(`y轴:` + window.scrollY);
windows方法
##### 提示、警示框
alert()
window.alert("message");弹出提示框,返回值是undefined
确认框
用户选择确认返回true,选择取消返回false
confirm()
let result = window.confirm("是否确认");//弹出对话框
console.log(result);//true或false
输入框
prompt()
用户输入信息,返回输入的信息
let input = window.prompt("请输入信息");//弹出对话框
console.log(input);//输入的信息
新建窗口
新建
open()
window.open("url","target","features");
参1:url:打开的页面的地址 参2:target:打开方式 _blank(新窗口)、 _self(当前页面) 参3:features:打开的页面的尺寸 参4:是否替换当前页面的历史记录(true,false)
resizeTo() 与resizeBy()
使用resizeTo()和resizeBy()方法可以调整浏览器窗口的大小。这两个方法都接受两个参数,其中resizeTo()接受浏览器窗口新宽度和新高度,而resizeBy()接受新窗口与原窗口的宽度和高度只差。
关闭
close()
let temp = window.open("./index2.html","_blank","width=300px,height=300px");//打开新窗口
//关闭窗口
temp.close();
时间函数
setInterval(callback,delay);
功能:每隔参数2的时间调用一次参数1 参1:callback:要执行的函数 参2:delay:每隔多少毫秒执行一次 参数3即以后都是参1的实参,建议第三个参数直接传要处理的对象或对象数组
clearInterval(timer);
参:定时器的名字
function getT(){
let date = new Date();
console.log(date.toTimeString());
}
setInterval(getT,1000);//每隔一秒执行一次函数
//练习:实现5,4,3,2,1
let k = 5;
let time = setInterval(() => {
console.log(k--);
if (k == 0) {
clearInterval(time);
}
}, 1000);
setTimeout(callback,delay);(超时函数)
功能:超过参数2的时间后,执行一次参数1的callback函数
clearTimeout(timer);
参:超时器的名字
let time1 = setTimeout(() => {
console.log("hello world");
}, 2000);
clearTimeout(time1);
BOM--history
Window.history是一个只读属性,用来获取History对象的引用,History对象提供了操作浏览器会话历史(浏览器地址栏中访问的页面,以及当前页面中通过框架加载的页面)的接口。
-
history.forward();向前跳转 -
history.back();向回跳转 -
history.go(n)通过参数的不同,返回不同的记录页面注:1、参数为正数,则去后面第n页 2、参数为负数,则去前面第n页 3、参数为0,则去当前页(刷新)
<a href="./bom2.html">上一页</a>
<input type="button" value="上一页" onclick="before()">
<input type="button" value="下一页" onclick="next()">
<script>
function before() {
history.back();
}
function next() {
history.forward();
}
</script>
BOM--location
location 获取地址栏信息
-
location.href获取地址栏的所有信息利用
location.href = "地址";跳转到指定的页面 -
location.search获取当前页面的查询字符串(?及以后的内容) -
location.port获取端口 -
location.replace("地址")替换当前页面,无法回退 -
location.assign("地址")跳转到指定页面
let info = location.href;//获取当前页面的地址
console.log(info);
let info1 = location.search;//获取当前页面的查询字符串(?及以后的内容)
console.log(info1);//?username=123&password=123123
let str = info1.split("?")[1];//获取查询字符串中的内容
let obj = formStrToObj(str);
console.log(obj) ;
console.log(formObjToStr(obj));
//获取端口
let port = location.port;//获取端口
console.log(port);//63342
//替换跳转页面
<input type="button" value="replace" onclick="F88()">
<input type="button" value="assign" onclick="F89()">
function F88(){
location.replace("/bom1.html");//替换当前页面
}
function F89(){
location.assign("/bom2.html");//跳转到指定页面
}
BOM--screen
屏幕信息
screen.availWidth获取屏幕可用宽度screen.availHeight获取屏幕可用高度
console.log(`屏幕宽度:${screen.availWidth}`);//可用屏幕宽度
console.log(`屏幕高度:${screen.availHeight}`);//可用屏幕宽度
BOM--navigator
浏览器信息
navigator.appName浏览器名称navigator.appVersion浏览器版本navigator.userAgent浏览器类型navigator.language浏览器翻译 zh-CN
console.log(`浏览器名称:${navigator.appName}`);//浏览器名称 Netscape网景 开源(免费)
console.log(`浏览器版本:${navigator.appVersion}`);//浏览器版本
console.log(`浏览器类型:${navigator.userAgent}`);//浏览器类型
console.log(`浏览器翻译:${navigator.language}`);//浏览器翻译 zh-CN
BOM--document(DOM)
Document Object Model 文档对象模型
作用:获取和操作HTML节点
DOM 发展历史
DOM0
DOM1 1998年 W3C
DOM2 2000年
DOM3 2004年
DOM4 2015年
节点对象
| nodeName(节点名) | nodeValue(节点值) | nodeType(节点类型) | |
|---|---|---|---|
| 元素节点(ElementNode) | 标签名 | null | 1 |
| 文本节点 (TextNode) | #text | 文本内容 | 3 |
| 属性节点 (AttributeNode ) | 属性名 | 属性值 | 2 |
获取节点
快速获取节点
通过标签名获取元素
document.getElementsByTagName("标签名");
如果找到对应的节点则会返回一个伪数组,可通过下标去访问某一个元素
如果没有找到,则伪数组length=0
let divElement = document.getElementsByTagName('div');
console.log(divElement[0]);
let secElement = document.getElementsByTagName('section')[0];
console.log(secElement);
通过类名获取元素
document.getElementsByClassName("类名");
如果找到对应的节点则会返回一个伪数组,可通过下标去访问某一个元素
如果没有找到,则伪数组length=0
let elementByClassName = document.getElementsByClassName('box1');//如果没有找到,返回length=0的伪数组
console.log(elementByClassName);
通过ID值获取元素
document.getElementById("id值");
ID具有唯一性,如何没有找到,返回null
扩展
可以直接书写id值,即为对应的节点对象
let elementByID = document.getElementById('isSection');//ID具有唯一性,如何没有找到,返回null
console.log(elementByID);
console.log(isSection);
通过节点的name属性值,获取元素
document.getElementsByName("username");
会返回一个伪数组,可通过下标去访问某一个元素
如果没有找到,则伪数组length=0
let inpEle = document.getElementsByName("username"); console.log(inpEle[1]);
查询选择器
获取元素节点的方式,与第一类快速获取节点相比不是实时的
css选择器怎么选择,选择器参数就如何传
document.querySelector()返回满足条件的第一个元素节点querySelectorAll()返回满足条件的所有元素节点
let elements = document.querySelector('[name="username"]');
console.log(elements);
//querySelectorAll()返回满足条件的所有元素节点
let elementsAll = document.querySelectorAll('[name="username"]');
console.log(elementsAll);
层次关系选取节点
子级
-
.childNodes获取所有子节点返回的是一个伪数组
let artEle = document.querySelector('article');
//获取所有子节点
console.log(artEle.childNodes);
-
.children获取所有子元素节点返回的是一个伪数组
//获取所有子元素节点
console.log(artEle.children);
console.log(artEle.children[1].children[0]);//span
.firstElementChild获取第一个子元素节点.lastElementChild获取最后一个子元素节点
//获取第一个子元素节点
console.log(artEle.firstElementChild);
.firstChild获取第一个子节点.lastChild获取最后一个子节点
//获取第一个子节点
console.log(artEle.firstChild);//文本节点
//获取最后一个子节点
console.log(artEle.lastChild);
父级
父级只有一个,所以父节点和父元素节点是同一个。
childNodes.parentNode获取父节点childNodes.parentElement获取父元素节点
注: 获取html的parentNode返回#document 获取html的parentElement返回null
console.log(artEle.parentNode.parentNode.parentNode);//document
console.log(artEle.parentElement.parentElement.parentElement);//null
兄弟
前面
-
ElementNode.previousSibling获取前一个兄弟节点 -
ElementNode.previousElementSibling获取前一个兄弟元素节点
console.log(spanElement.previousSibling);//文本节点
console.log(spanElement.previousElementSibling);//span1
后面
ElementNode.nextSibling获取后一个兄弟节点ElementNode.nextElementSibling获取后一个兄弟元素节点
console.log(spanElement.nextSibling);//文本节点
console.log(spanElement.nextElementSibling);//span3
parentNode.hasChildNodes(childNode)可以判断父节点里面是否包含子节点
简单获取节点
document.documentElement 获取HTML
document.head 获取head
document.body 获取body
document.images
document.forms 所有的form标签
document.links 所有的a标签
新增元素节点
- 创建新的元素节点 书写格式:
document.createElement(nodeName) - 创建新元素节点的元素内容(文本) 书写格式:
document.createTextNode(text) - 把新增的节点添加到页面中 书写格式:
parentNode.appendChild(childNode)
//书写格式:document.createElement(nodeName)
let divElement2 = document.createElement('div');
console.log(divElement2);
//添加节点
//书写格式:parentNode.appendChild(childNode)
let bodyElement = document.querySelector('body');
bodyElement.appendChild(divElement2);
//添加文本节点
//书写格式:document.createTextNode(text)
let divText = document.createTextNode('这是新增的文本节点');
//书写格式:elementNode.appendChild(textNode)
divElement2.appendChild(divText);
console.log(divText);
插入节点
需要的节点
- 父节点
- 被插入的节点
- 插入的节点(新)
步骤
- 新增或获取插入节点
- 获取父节点
- 获取被插入的子节点
- 执行插入节点书写格式 书写格式:
parentNode.insertBefore(insertNode,childNode)
注释节点
书写格式:document.createComment(text)
let comment = document.createComment('这是注释节点');
bodyElement.insertBefore(comment, divElement2);
剪切节点
方式1:如果插入的节点已经存在页面中,插入后,会在原位置删除
方式2:如果添加的节点已经存在页面中,添加后,会在原位置删除
//方式1
let pElement = document.querySelector('p');
bodyElement.insertBefore(pElement,divElement2 );
//方式2
let divElement3 = document.querySelector('.box');
bodyElement.appendChild(divElement3);
复制(克隆)节点
书写格式: 被克隆的节点.cloneNode(boolean)
-
实参给true,则表示深克隆,会克隆其子节点
-
实参给false,则表示浅克隆,不会克隆其子节点
let divElement3 = document.querySelector('.box');
let divClo = divElement3.cloneNode(false);
bodyElement.appendChild(divClo);
更改、替换
书写格式:parentNode.replaceChild(newChild,oldChild)
let asideElement = document.createElement('aside');
bodyElement.replaceChild(asideElement,divElement2);
快速替换或覆盖的方式
快速替换元素内容
- innerHTML可以识别字符串里面的标签
- innerText只能识别文本,不能识别标签
ple2.innerText = '<i>这是新的文本</i>';
ple2.innerHTML = '<i>这是新的文本</i>';
删除
书写格式:parentNode.removeChild(childNode)
bodyElement.removeChild(divElement3);
属性节点(AttributeNode)
生成属性节点
书写格式:ElementNode.setAttribute(name,value)
let headerElement = document.getElementsByTagName('header')[0];
headerElement.setAttribute('name', 'f82');
获取属性(原生和添加属性均可获取)
书写格式:ElementNode.getAttribute(name)
console.log(headerElement.getAttribute('name'));
注:ElementNode.属性名 仅可使用元素节点原生的属性
获取class属性值(多个)
可以通过ElementNode.classList获取,返回伪数组,即可通过下标获取
let asideElement11 = document.getElementsByTagName('aside')[0];
console.log(asideElement11.getAttribute('class'));//y1 y2(一个值)
console.log(asideElement11.className);//y1 y2(一个值)
console.log(asideElement11.classList);//[y1,y2] 伪数组
console.log(asideElement11.classList[1]);//y2
asideElement11.classList.add('y3');//添加class y3
asideElement11.className = 'y3';//将y1 y2替换成y3
asideElement11.className += ' y4';//将y4添加到y3后面,注意加空格
asideElement11.classList.remove('y3');//删除class y3
删除属性
书写格式:ElementNode.removeAttribute(name)
headerElement.removeAttribute('name');
快速生成属性
书写格式:ElementNode.属性名 = 属性值
注意:for写成htmlFor;class写成className
自定义属性
书写格式1:<开始 data-属性名=属性值></结束>
书写格式2:ElementNode.dataset.属性名 = XXX
获取自定义属性
书写格式1:ElementNode.dataset.属性名
书写格式2:ElementNode.getAttribute(name)
补充:
//创建文档碎片(实现添加多个标签时,只渲染一次),减少DOM渲染的次数,提高效率
let frag = document.createDocumentFragment();
frag.appendChild(spanEle);//将多个标签加入临时碎片
sectionEle.appendChild(frag);
利用js操作CSS
设置:ElementNode.style.key = value;
获取:ElementNode.style.key
注意:
- key是css样式的键名,如果是多个单词组成,则去横线,并且小驼峰;value是css样式的值
- 以点的方式只能获取节点的行内样式,非行内样式返回空
let labelElement = document.getElementsByTagName('label')[0];
labelElement.style.color = 'red';
labelElement.style.backgroundColor = 'blue';
labelElement.style.fontSize = 60+'px';//去掉连接符,使用小驼峰命名法
console.log(labelElement.style.color);//red
console.log(labelElement.style.fontSize);//60px
console.log(labelElement.style.border);//none
获取节点计算后的样式
书写格式 :getComputedStyle(ElementNode)
功能:实现获取非行内样式
注意:该样式为只读属性
let labelStyle = getComputedStyle(labelElement);
console.log(labelStyle.paddingLeft);//30px
获取元素节点的尺寸
- content的宽高
ElementNode.style.width 带单位px 可用parseInt来提炼数值
ElementNode.style.height 带单位px 可用parseInt来提炼数值
- content+padding
ElementNode.clientWidth
ElementNode.clientHeight
- content+padding+border
ElementNode.offsetWidth
ElementNode.offsetHeight
获取节点的位置
position不等于static 获取节点到包含块的距离
position 等于static 获取节点到视口的距离
offsetLeft,offsetTop
let {offsetLeft,offsetTop} = iEle;//对象的解构
console.log(offsetLeft,offsetTop)
事件
事件:当用户在页面操作行为时则会触发事件
事件三要素:
- 事件源 (绑定事件的节点)
- 事件类型 (键盘、鼠标等) 例如:onclick
- 事件处理函数 (事件触发时执行的函数) 例如:F82()
- DOM0
- DOM0级事件绑定 会存在覆盖的问题;下边的代码会把上边的代码覆盖.
- 分为两种:一种是 onclick = function(){} ,还有一种是标签内写onclick事件
- DOM0级事件具有极好的跨浏览器优势,会以最快的速度绑定。
- 删除DOM 0事件处理程序,只要将对应事件属性设为null即可。
box.onclick = null;
- DOM1
DOM1一般只有设计规范没有具体实现,所以一般跳过。
- DOM2
- 原生有两个方法用来添加和移除事件处理程序:
addEventListener()和removeEventListener()。 - 给某一个元素的同一个行为绑定不同的方法在行内会分别执行;支持绑定多个函数;只有三个参数都相同时,才称为重复绑定,这时就不再往 事件池 添加 事件
- 第三个参数如果是true则表示在捕获阶段调用,为false表示在冒泡阶段调用。
- 只有2级DOM包含3个事件:事件捕获阶段、处于目标阶段和事件冒泡阶段;需要对同一个节点触发不同的事件时,事件不会被覆盖,会依次执行,dom1和dom2是可以共存的
ElementNode.addEventListener(事件类型,事件处理函数,事件流)
-
addEventListener的第三个参数:事件流——事件传播机制
-
取值:Boolean
- 取值为false则从里到外依次触发,即冒泡(不写则默认false)
- 取值为true则从外到里依次触发,即捕获
-
具有嵌套关系 + 相同的事件类型就需要考虑事件流
事件类型
鼠标事件
click单击dblclick双击mousedown按下mouseup抬起- 【鼠标移入——移出】
- 这一组事件源与子元素都会触发
mouseover移入mouseout移出
- 这一组只有事件源触发(true----捕获时 子元素也会触发效果)
mouseenter移入mouseleave移出
- 这一组事件源与子元素都会触发
mousemove鼠标移动
获取鼠标的左、中、右键
document.addEventListener('click',function(e){
let event = e ||window.event;
//左、中、右 ————>0、1、2
console.log(event.button);
});
获取鼠标在盒子内的坐标
1. 首先得到鼠标在页面中的坐标( e.pagex e.pageY )
2. 其次得到盒子在页面中的距离( box.offsetLeft, box.offsetTop)
3. 用鼠标距离页面的坐标减去盒子在页面中的距离,得到鼠标在盒子内的坐标
console.log("鼠标到节点的X轴:", event.offsetX);
console.log("鼠标到节点的Y轴:", event.offsetY);
console.log("鼠标到视口的X轴:", event.clientX);
console.log("鼠标到视口的Y轴:", event.clientY);
console.log("鼠标到页面的X轴:", event.pageX);
console.log("鼠标到页面的Y轴:", event.pageY);
页面事件
页面加载:
//已加载
window.addEventListener('load',f);
//AD
window.addEventListener('load', function () {
asiEle.style.bottom = 0 + 'px'
//关闭功能
//倒计时功能
let i = 5;
let timer = setInterval(() => {
timeSpan.innerText = `${i}`;
if (i < 0) {
asiEle.remove();
clearInterval(timer);
}
i--;
}, 1000);
xSpan.addEventListener('click', () => {
clearInterval(timer);
asiEle.remove();
});
});
检测滚动条
scroll 事件类型用于在浏览器窗口内移动文档的位置时触发,如通过键盘箭头键、翻页键或空格键移动稳定位置,或者通过滚动条滚动稳定位置。利用该事件可以跟踪文档位置变化,及时调整某些元素的的显示位置,确保它始终显示在屏幕可见区域内中。
window.addEventListener('scroll',()=>{
let secEle = document.getElementsByTagName('section')[0];
let scrollYs = window.scrollY;
secEle.style.display = 'none';
if (scrollYs < 800){
secEle.style.display = 'none';
}else {
secEle.style.display = 'block';
}
});
关闭或刷新
window.addEventListener('unload',function(){})
键盘事件
keydown:按下键盘时触发 注:按住不放一直触发该事件
event.key获取按的那个键
event.keyCode获取按键的ASC码
input.addEventListener('keydown',function(e){
e=e||window.event;
if(e.key == 'Enter'){
}
})
keyup 抬起按键时触发
keypress 按下键盘的字符键时触发,功能键不触发
字符键:字母、数字、标点符号、shift+0-9
表单事件
focus 激活焦点框 移入输入框时触发
input 输入时触发
blur 失去焦点 移出输入框时触发
change 失去焦点时input的值与激活焦点时的值不一样的时候触发
即失去焦点前与失去焦点后的内容是否一致,如果不一致(发生改变)则触发该事件 适用场景 :select
补充:获取焦点 ElementNode.focus()
reset 重置按钮(reset 按钮触发) submit 提交事件 (提交按钮触发)
事件委托、事件代理
触发事件的节点
当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递给响应函数
在事件对象中封装了当前事件相关的一切信息,比如:鼠标的坐标,键盘哪个按键被按下,滚轮的滚动方向
在IE8中,响应函数被触发时,浏览器不会传递事件对象,在IE8中及以下的浏览器中,是将事件对象作为window对象的属性保存的
事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
事件对象是触发事件时会自动传入到事件处理函数的一个对象,该对象里面记录了触发事件的详细信息。
适用场景:
-
相同事件类型
-
子节点是动态的
let ulEle = document.getElementsByTagName('ul')[0];
ulEle.addEventListener('click',function(e){
//解决事件对象的兼容性问题
let event = e || window.event;
//event.target触发事件的节点
if(event.target.nodeName == 'LI'){
console.log('li');
}
if(event.target.localName == 'span'){
console.log('span');
}
})
事件处理函数(普通声明)中的this代表的就是事件源
cancelable 取消
事件阻止
-
阻止冒泡型事件流(DOM2) 书写格式:事件对象.stopPropagation() 事件对象是内层的
-
阻止捕获型事件流(DOM3) 书写格式:事件对象.stopImmediatePropagation() 事件对象是外层的
-
阻止默认事件:阻止原始的功能,执行需要的业务逻辑 书写格式:事件对象.preventDefault() (按钮和a标签可能用到)
//借助Mock批量生成数据
let result = Mock.mock({
"stuArr|10":[{
"stuId|+1":1,
"stuName":"@cname",
'stuAge|20-30':1,
'stuGender|1':[true,false]
}]
});
console.log(result);