JS的组成部分BOM和DOM

250 阅读10分钟

BOM

 全称Browser Object Model,为浏览器的对象模型,是用对象来描述的一个结构,是通过对象组成的结构来操作浏览器。 浏览器中历史记录是window的子对象,可以进行网页的前进和后退。

例如:

history.backe()返回到上一个页面,等于浏览器的后退按钮
history.forward()前进到下一个页面,必须是点击后的页面,等于浏览器的前进按钮
history.go()可以前进一个页面或者多个页面,给正数是前进,给负数是后退,前进或者后退多个页面根据给的数字来定。

location是处理浏览器地址栏,为window对象的子对象。

console.log(location.hash)设置或返回从#开始的url---锚点
console.log(location.href)设置或者返回完整的url
console.log(location.search)设置或者返回url中的参数部分
语法:location.assign('需要跳转的地址')
      location.reload()重新加载页面
      location.replace()使用新地址替换掉旧地址(跳转)

浏览器中会出现弹出层。

window.alert('恭喜你')
window.prompt('请输入数字:'1)
window.confirm('你确定?')

 设置浏览器窗口的尺寸。这两个属性返回的单位是像素,计算的范围包含滚动条的区域window.innerHeight - 浏览器窗口的高度 window.innerWidth -浏览器的宽度

var w = window.innerwidth;
console.log(w);
var h = window.innerHeight;
console.log(h)

浏览器事件,onload事件是当网页中的所有资源都加载完成之后执行这个事件。通常是将script标签放到head标签中的时候使用。因为放在head中默认是获取不到body中的内容的,但是有了这个事件后,就可以了。

window.onload = function(){
console.log("当网页中所有资源加载完成才打印");}

onscroll 滚动事件:当网页滚动条的位置发生改变的时候触发这个事件,浏览器要有滚动条才行。

window.onscroll = function () {
console.log('浏览器滚动了')}

浏览器窗口改变事件:resize.第一个参数是要执行的函数,第二个参数延迟的时间(单位毫秒)。返回一个数字,表示当前页面中第几个定时器

  window.onresize = function(){
    // 当浏览器的窗口大小发生改变的时候触发这个事件}

隔一段时间执行,第一个参数是要执行的函数,第二个参数是间隔的时间(单位毫秒)。返回一个数字,表示当前页面中第几个定时器。

var timerId = setInterval(function () {
 console.log('我执行了')}, 1000)

关闭定时器:定时器返回的数字,就是用来关闭定时器的

clearTimeout(timerId); // 关闭延迟执行的定时器
clearInterval(timerId); // 关闭间隔执行的定时器

延迟执行和间隔时间可以混合使用。

var timerId = setTimeout(function () {
 console.log('倒计时定时器')
}, 1000)// 关闭延迟执行定时器
clearInterval(timerId)

var timerId2 = setInterval(function () {console.log('间隔定时器')}, 1000)// 关闭间隔定时器
clearTimeout(timerId2)

异步操作

js的异步操作,是在所有同步代码执行完成以后才执行异步代码。 一般情况代码是按顺序执行的,上一行代码执行结束之前,下一行代码一直在等待,这是同步机制。

同步:
console.log(1)
console.log(2)
异步:
setTimeout(function){
console.log(1)
},0)
console.log(2)

窗口控制

打开新的窗口

语法:

window.open(url, 窗口名称, 窗口风格)
如果url为空,会打开一个空的标签页;url不为空,就打开目标url页面
窗口名称是一个字符串
窗口风格:
	height:窗口高度,数字,不能小于100
	width:窗口高度,数字,不能小于100
	left:窗口左边距离,数字
	top:窗口上边距离,数字

关闭窗口:

window.close()

DOM

DOM的全拼是:Document Object Model,叫做文档对象模型。就是使用对象结构操作html文档。例如,改变标签的背景颜色,让标签移动产生动画。DOM中的顶级对象是document,言外之意,DOM其实是属于BOM. 例如:
window.document.write();
window.document.bgColor="red";

html基本结构的操作:

1.document.body :body比较常用, 并且在页面中是唯一的, 因此可以使用document.body直接获取 2.document.documentElement : 可以获取html元素及其所有内容 3.document.head : 可以直接获取head元素 4.document.title : 可以直接获取title的文本

 在js中,标签的id名,可以当做是变量,直接就能代表这个标签元素,但是,id名可以随便定义,但是变量名不能随便定义,所以使用id名代表标签是有风险的。所以需要通过方法来获取到标签元素,自己定义给变量,可以避免这种风险。 通过document获取节点

document.getElementById("标签id名"); // 通过标签的id名获取标签
document.getElementsByTagName("标签名"); // 通过标签名获取标签
document.getElementsByClassName("标签类名"); // 通类名获取标签
document.getElementsByName("标签的name属性的值"); // 通过标签的name属性获取标签
// 上述4种获取标签的方法,除了通过id可以准确获取到元素,别的方法都是只能获取到元素的集合(类数组)

使用css选择器获取元素:
documen.querySelector(css选择器); // 获取到匹配css的第一个元素
documen.querySelectorAll(css选择器); // 获取到匹配css的所有元素

内容操作

语法: 元素.innerHTML # 代表元素中的所有内容(包含标签) 元素.innerText # 代表元素中的文本内容 表单元素.value # 单标签操作内容其实就是在操作元素的属性

样式操作

设置样式:元素.style.css属性名 = css属性值; # 给标签设置样式

获取样式:window.getComputedStyle(标签),返回所有样式键值对组成的对象。

元素类名

使用元素的className属性可以设置元素的类名,也可以获取类名
<body>
 <div class="box"></div>

 <script>
   var div = document.querySelector('div')
  	div.className = 'test'
   console.log(div) // <div class="test"></div>
     
   console.log(div.className) // test
 </script>
</body>

属性操作

标签属性:
元素.setAttribute(属性名,属性值) # 设置元素的属性
元素.getAttribute(属性名); # 获取元素属性
元素.removeAttribute(属性名); # 删除元素属性

对象属性:元素.属性名 = 值; console.log(元素.属性名); 例如:

btn.onclick=function(){
    img.src = '2.jpg';}

H5的自定义属性操作,当给标签添加属性以date-xxx开头时,H5提供了一个快速操作属性的api:标签.dataset.XXX // 获取属性的值

页面卷去的距离

document.documenElement.scrollTop,次语法当HTML没有文档声明的时候是获取不到的。

document.body.scollTop,此语法可以获取到

兼容写法:var t = document.documentElement.scrollTop || document.body.scrollTop

短路运算

利用逻辑运算中的&和||让赋值操作变得更灵活,并带有选择性,当数据1为true,不能决定整个条件的结果,还需要进行到数据2,所以此时会将数据2赋值给变量。当数据1为false,就已经知道整个条件的结果了,就没有必要进行到数据2了,所以此时会将数据1赋值给变量。当数据1为true,就已经能决定整个条件的结果了,就没有必要进行数据2了,此时就将数据1赋值给变量 当数1为false,还不能决定整个条件的结果,需要进行到数据2,此时就会将数据2赋值给变量。书写:var 变量 = 数据1 && 数据2

节点操作

在js中,DOM、标签、书写的文本是由节点组成,DOM的节点有:元素节点、文本节点、属性节点。元素节点是获取到的标签元素,标签元素中的文本就是文本节点,标签中的属性就是属性节点。

如何获取节点

1.获取所有子标签的节点:父.children
2.获取第一个子标签节点:父.firstElementChild
3.获取最后一个子标签节点:父.lastElementChild
4.获取父标签节点:子.parentElement
5.获取上一个兄弟标签节点:标签.previouseElementSibling
6.获取下一个兄弟标签:标签.nextElementSibling

创建标签

document.createElement('标签名字符串') -- 返回创建好的标签

var div = document.createElement('div')
 div.innerText = '盒子'
 div.className = 'box'
 div.style.width = '200px'
 div.setAttribute('name', 'mybox')
 console.log(div);

插入节点

给父标签追加子标签 父.appendChild(子标签对象) 将新的子标签插入到某个旧的子标签前面 父.inserBefore(新的子标签,旧的子标签)

document.body.appendChild(div)
document.body.insertBefore(div, ul)

替换节点

使用新的子标签替换掉旧的子标签 父.removeChild(新的子标签,旧的子标签)

var b = document.createElement('b')
 b.innerText = '加粗'
 使用b标签替换掉fourth
 父.replaceChild(新, 旧的子标签)
 ul.replaceChild(b, fourth)

删除节点

父标签将指定的子标签删除 父.removeChild(子标签)

克隆节点

将一个标签复制一份出来 标签.cloneNode()

 console.log( fourth.cloneNode() );
 如果要将标签中的内容和子标签都复制出来,就给方法添加参数true
 console.log( fourth.cloneNode(true) );

获取标签尺寸

包含标签边框的尺寸 标签.offsetWidth 标签.offsetHeight
var w2 = box.offsetWidth
var h2 = box.offsetHeight
console.log(w2, h2);

不包含边框的尺寸

var box = document.querySelector('.box')
var w1 = box.clientWidth
var h1 = box.clientHeight
console.log(w1, h1);

获取元素位置

标签.offsetLeft 标签.offsetTop
var l1 = big.offsetLeft
var t1 = big.offsetTop
console.log(l1, t1);

var small = document.querySelector('.small')
var l2 = small.offsetLeft
var t2 = small.offsetTop
console.log(l2, t2);

获取边框的大小

标签.clientLeft 标签.clientTop
var box = document.querySelector('.box')
var l = box.clientLeft
console.log(l);

var t = box.clientTop
console.log(t);

回流和重绘

通常一个标签要设置很多样式。为了方便我们批量设置样式,可以封装一个批量设置样式的函数,这个函数在批量设置样式的时候,每遍历一次,设置一次样式,每次设置样式都设置在了行内,这样会造成多次回流,影响页面性能。
function setStyle(ele, styleObj) {
    for(var key in styleObj) {
        ele.style[key] = styleObj[key]
    }
}

浏览器渲染过程

1695040707898.jpg

回流

英文叫reflow,指的是当渲染树中的节点信息发生了大小、边距等问题,需要重新计算各节点和css具体的大小和位置. 容易造成回流的操作:
  • 布局流相关操作

    • 盒模型的相关操作会触发重新布局
    • 定位相关操作会触发重新布局
    • 浮动相关操作会触发重新布局
  • 节点操作

    改变节点的结构或其中的文本结构会触发重新布局。

    对标签进行下面这些属性或方法操作的时候,会强行回流:

    -   offsetTop
    -   offsetLeft
    -   offsetWidth
    -   offsetHeight
    -   scrollTop
    -   scrollLeft
    -   scrollWidth
    -   scrollHeight
    -   clientTop
    -   clientLeft
    -   clientWidth
    -   clientHeight
    -   getComputedStyle

-   css

    -   width
    -   height
    -   padding
    -   border
    -   margin
    -   position
    -   top
    -   left
    -   bottom
    -   right
    -   float
    -   clear
    -   text-align
    -   vertical-align
    -   line-height
    -   font-weight
    -   font-size
    -   font-family
    -   overflow
    -   white-space

重绘

英文叫repaint,当节点的部分属性发生变化,但不影响布局,只需要重新计算节点在屏幕中的绝对位置并渲染的过程,就叫重绘。比如:改变元素的背景颜色、字体颜色等操作会造成重绘。 回流的过程在重绘的过程前面,所以回流一定会重绘,但重绘不一定会引起回流。 容易造成重绘操作的css:

-   color
-   border-style
-   border-radius
-   text-decoration
-   box-shadow
-   outline
-   background

合并样式修改 减少造成回流的次数,如果要给一个节点操作多个css属性,而每一个都会造成回流的话,尽量将多次操作合并成一个

var oDiv = document.querySelector('.box');
oDiv.style.padding = '5px';
oDiv.style.border = '1px solid #000';
oDiv.style.margin = '5px';

批量操作DOM 当对DOM有多次操作的时候,需要使用一些特殊处理减少触发回流,其实就是对DOM的多次操作,在脱离标准流后,对元素进行的多次操作,不会触发回流,等操作完成后,再将元素放回标准流

ar data = [
    {
        id:1,
        name:"商品1",
    },
    {
        id:2,
        name:"商品1",
    },
    {
        id:3,
        name:"商品1",
    },
    {
        id:4,
        name:"商品1",
    },
    // 假设后面还有很多
];
var oUl = document.querySelector("ul");
for(var i=0;i<data.length;i++){
    var oLi = document.createElement("li");
    oLi.innerText = data[i].name;
    oUl.appendChild(oLi);
}