BOM和DOM

本文详细介绍了浏览器对象模型BOM中的history和location对象,包括如何操作浏览器的历史记录和地址栏。同时,讲解了DOM的基本操作,如获取和设置标题、内容以及属性,还涉及了事件监听,如onload、onscroll和onresize。此外,讨论了JavaScript中的定时器和异步编程概念,以及DOM的属性和样式操作,包括内容的获取与设置、属性的增删改查以及类名的管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

BOM:Browser Object Model - 浏览器对象模型

浏览器对象模型:操作浏览器的 一套 用对象组成的结构

历史记录操作 - history

console.log(window.history);

  1. 返回到上一个页面,相当于浏览器的后退按钮

window.history.back()

2.前进到下一个页面(下一个页面必须是点击以后的页面),相当于浏览器的前进按钮

window.history.forward()

3.后退多个页面

window.history.go(-2)

go可前进可后退多个页面,具体是几个页面,就看数字是几,前进正数,后退负数

案例:

地址栏操作 -- location

操作地址栏使用 window.location

在操作的时候可以省略window

console.log(location);

1.href - 获取整个地址url或设置整个地址url(跳转)

console.log( location.href );

我们获取到的是经过url编码的数据 - 默认情况下,地址栏中的url会自动进行url编码

解码 - decodeURI(被编码的数据)

编码 - encodeURI(要编码的数据)

location.href = 'http://baidu.com' // 跳转地址

2.search - 获取/设置 整个url中的数据部分

console.log( location.search );

// location.search = '?name=zhangsan'

// btn.onclick = function() {

// location.search = '?age=18'

// }

3.hash - 获取/设置 - 整个地址中的锚点

console.log( location.hash ); -- 获取整个地址栏的锚点

location.hash = '#666' ; -- 设置整个地址栏的锚点

4.跳转页面 -- assign , replace

btn.onclick = function() {

location.assign('http://qq.com') -- 跳转页面

location.replace('http://music.163.com') -- 用新地址把旧地址替换掉

5. 刷新页面 -- reload

location.reload()

总结:

location.href - 整个地址

location.search - url中的数据部分

location.hash - url中的锚点部分

浏览器的弹出窗口(可以省略window)

window.alert("恭喜你!");

window.prompt("请输入数字:",1);

window.confirm("你确定要删除吗?")

window代表的是浏览器窗口 - 大小

window.innerWidth - 浏览器窗口的宽度

window.innerHeight - 浏览器窗口的高度(window可省略)

浏览器的事件

1.window.onload - 当网页中的所有资源都加在完成之后执行这个事件

2.window.onscroll - 当滚动条动了,就会触发执行的事件

3.window.onresize - 当浏览器大小发生改变,就会触发执行的事件

窗口控制

window.open(目标地址) - 打开新窗口

window.close() - 关闭当前窗口

window.scrollTo(x, y) - 控制窗口滚动 - 设置卷去的距离

定时器(异步代码)

  1. 让一个函数每隔一段时间就执行一次,会不停的执行

语法:window.setInterval(函数代码, 毫秒数) - 返回一个数字,代表当前页面中第几个定时器

停止定时器 - clearInterval(返回值)
2.让一个函数延迟一段时间执行,只能执行一次

语法:setTimeout(函数代码, 毫秒数) - 返回的数字,当前页面中的第几个定时器

在代码还没执行的时候点击停止会终止运行,不输出

同步和异步

定时器是我们学过的第一个异步代码(效率更高) --- 两段代码执行的时间差一秒

js和异步的关系

js是单线程语言

进程:为了让一个软件/服务能正常运行 而 分配的内存空间

线程:进程会造成内存浪费,所以就有更小的内存空间 - 线程

js只有一个内存空间在运行代码 - 同一时间只能运行一个代码,不能运行多个代码

js是如何实现异步代码的?

js在执行代码的时候,碰到了同步代码,就开始执行,碰到了异步代码,就将异步代码交给浏览器去处理

浏览器为什们能帮js处理异步代码?浏览器是多线程软件 - 同一时间做多件事情

浏览器在替js等待定时器的时间 - 如果时间到了,浏览器会将需要执行的函数,放在一个队列中排队等待

当js将所有的同步代码都执行结束后,再去队列中,依次执行排队的代码

总结

1.定时器给的时间不精准

2.异步代码一定会在所有同步代码执行结束后才会执行

DOM:document object model - 文档对象模型

顶级对象 document window.document

用来操作文档 - html文档

DOM操作html基本结构

1.body:document.body

console.log(document.body);

2.html:document.documentElement

console.log( document.documentElement );

3.console.log(document);

document-代表整个文档

4.head:document.head

console.log(document.head);

5. 操作文档标题 - document.title

console.log(document.title); // 获取标题

获取标签

css选择器

css选择器:类选择器,id选择器,标签选择器,后代选择器,子元素选择器,兄弟选择器,伪类选择器,群组选择器,通配符选择器,属性选择器-- 语法[属性名=属性值](和类名选择器的权重一样高)

1.语法:document.querySelector('css选择器') -- 选择满足css选择器的第一个元素

2.语法:document.querySelectorAll('css选择器') -- 满足css选择器的所有元素都选中

dom中所有能代表标签的变量,他们的数据类型一定是object(只要是标签,它就是对象)

dom中元素的特性:console.log输出的时候都是标签的样子,不是对象的样子

console.dir(oDiv) //可以把一些数据原本的样子展示出来

可以遍历

总结:

获取标签

document.querySelector('css选择器') - 获取一个

document.querySelectorAll('css选择器') - 获取多个

获取到的标签 - 是一个对象 - console.log只能看到标签 - 想看到对象使用console.dir

获取到的集合 - 是一个伪数组,可以遍历、取下标、可以有长度,就是不能使用数组方法

其他获取标签的方式(一般不用)

操作标签内容

(双标签)

获取标签

var oDiv = document.querySelector('div')

console.log(oDiv);

获取内容
标签.innerText - 只能获取到文本内容(避免使用集合)

console.dir(oDiv)

console.log(oDiv.innerText);

获取带有标签的内容 - 标签.innerHTML

console.log(oDiv.innerHTML);

设置内容

oDiv.innerText = 'div标签' --- 只能识别文本

oDiv.innerHTML = '<b>div标签</b>'

表单标签

<input type="text" value = "请输入一段文字">

获取标签

var oInput = document.querySelector('input')

// 表单标签 - 内容操作使用 表单标签.value

console.log(oInput.value); // 请输入一段文字

设置内容

oInput.value = '内容不能为空' //把请输入一段文字换成 内容不能为空

总结:

双标签内容

文本内容

标签.innerText - 可以获取文本内容/设置文本内容

带标签内容

标签.innerHTML - 可以获取带标签的内容/设置带标签的内容

表单标签内容

表单标签.value - 可以设置/可获取

坑1:操作内容,必须是 具体的 标签.属性 来操作,不能是 集合.属性 操作

坑2:不管是设置文本内容还是带有标签的内容,原本的内容就不见了,被覆盖掉了

属性操作
操作标签的属性

标签的属性-<标签 键=值> - 长在标签上的键值对

获取属性

标签.getAttribute('属性名') -- 返回是属性的值

设置属性

标签.getAttribute('属性名','属性值')

删除属性

标签.removeAttribute('属性名')

样式操作
设置样式

标签.style.css的键 = 'css的值' --- 设置在行内了 (JS中为了方便设置样式(如果css的键里面有连字符)那就换成小驼峰命名法)

例:oDiv.style.backgroundColor = '#0f0'

获取样式

window.getComputedStyle(标签) - 返回一个有所有样式键值对组成的一个对象

案例:

<style>
    .box {
        width: 100px;
        height: 100px;
        background-color: yellow;
    }
</style>

<body>
    <div class="box">盒子</div>
</body>
 <script>
   var oDiv = document.querySelector('div')
    //点击div让宽度加大到500
    oDiv.onclick = function () {
        //(1.)变大 - 设置定时器
        var timer = setInterval(function () {
            //(3.)获取原来的值
            var obj = getComputedStyle(oDiv)
            var width = obj.width
            // console.log(width);
            width = parseInt(width)


            //(4.)加大
            width += 2
            // console.log(width);

            //只能加到500,限定最大值
            if (width >= 500) {
                width = 500
                //把定时器停下来
                clearInterval(timer)
            }

            //(2.) 给div加宽 - 重新设置宽度样式,值比原来的大
            oDiv.style.width = width + 'px'
            //输出一个值,看定时器什么时候停下来
            console.log(width)
        }, 16)
    }
</script>

类名操作
获取/设置类名

标签.className

清空所有类名 (赋值为空)

oDiv.className = ' '

添加类名

标签.classList.add(类名)

删除类名

标签.classList.remove(类名)

让类名再添加和删除之间切换

标签.classList.toggle(类名)

不在会添加,在的话会删除

判断类名是否存在(返回布尔值)

标签.classList.contains(类名)

切换背景颜色案例
<style>
    .box{
        width: 200px;
        height: 200px;
        border: 1px solid #999;
    }
    .box>div{
        width: 100px;
        height: 100px;
        float: left;
    }
    .box>div:nth-child(1){
        background-color: red;
    }
    .box>div:nth-child(2){
        background-color: yellow;
    }
    .box>div:nth-child(3){
        background-color: skyblue;
    }
    .box>div:nth-child(4){
        background-color: palegreen;
    }
</style>
<body>
    <div class="box">
        <div></div>
        <div></div>
        <div></div>
        <div></div>
    </div>
</body>

<script>
var divs = document.querySelectorAll('.box div')
// console.log(divs);
for(var a = 0; a < divs.length; a++){
 (function(a) {
        divs[a].onclick = function(){
                // console.log(a)
                var color = getComputedStyle(divs[a])['background-color']
                console.log(color)
                //给当前网页设置背景颜色
                document.body.style.backgroundColor = color
            }
    })(a)
}
</script>

页面卷去的距离

有文档声明的时候

document.documentElement.scrollTop

没有文档声明的时候

document.body.scrollTop

兼容写法

document.documentElement.scrollTop || document.body.scrollTop

短路运算

短路运算通常使用 || 和 &&

可以用于赋值 -- 看看代码是否能进行到最后(符号的右边),如果能进行到右边,就会将右边的值赋值给

变量;如果进行不到右边,就将左边的值赋值给变量.

利用逻辑运算,查看左边的结果是否能决定整体的结果

节点操作

根据标签之间的关系获取标签
获取子标签

获取所有的子标签节点 -- 父.children

eg: var ul = document.querySelect('ul')

console.log(ul.children)

获取第一个子标签节点-- 父.firstElementChild

console.log(ul.fristElementChild)

获取最后一个子标签节点 -- 父.lastElementChild

console.log(ul.lastElementChild)

获取父标签 -- 子.parentElement

var last = ul.lastElementChild (把最后一个子标签存在last里面)

console.log(last.parentElement)

获取上一个兄弟标签节点

标签.previousElementSibling

获取下一个兄弟标签节点

标签.nextElementSibling

创建标签

document.createElement('标签名字符串')

把标签插入到文档中

1.给父追加一个子 - 将这个标签作为某个父标签的最后一个儿子

语法:父.appendChild(子)

2.将标签放在某个父标签的某个子标签的前面

语法:父.insertBefore(新的子, 旧的子)

替换标签

使用新的子标签替换掉旧的子标签:

语法:父.replaceChild(新, 旧)

删除

父标签将指定的子标签删除:

语法:父.removeChild(子)

复制

将一个标签复制一份出来:

语法:标签.cloneNode() - 返回一个标签对象,这样只能复制一个空的标签,没有内容

带内容的复制 -- 返回一个标签对象,这样可以将标签中的内容也复制出来。

语法: 标签.cloneNode(true)

获取标签尺寸

包含标签边框的尺寸:

标签.offsetWidth

标签.offsetHeight

不包含边框的尺寸

标签.clientWidth

标签.clientHeight

获取元素位置

获取的是相对于设置过定位的父标签的左边距和上边距离,返回纯数字。

标签.offsetLeft

标签.offsetTop

参考设置过定位的祖宗标签,如果祖宗没有定位,就参考html标签

获取边框厚度

获取到的是上边框和左边框的厚度,纯数字。

标签.clientTop

标签.clientLeft

获取标签名

标签.tagName -- 大写的标签名

回流和重绘

浏览器的渲染过程

html结构和css代码同时开始解析,html结构最终被解析成一棵dom树,css代码被解析成一个样式规则 ,dom树和样式规则合并成一颗渲染树. 渲染树开始进行布局(计算标签的大小和位置); 布局完成以后开始绘画(涂颜色),最后将页面显示出来.

如果重新需要布局,那就造成回流了

如果重新绘画,那就造成重绘了

不管是回流还是重绘,都对浏览器渲染造成了性能的影响,为了优化这个性能,我们可以有三个优化手段

  1. 样式的合并

  1. 减少dom的一些操作

  1. 定时器中减少回流

容易造成回流的操作:

布局流相关操作

节点操作

css

优化
合并样式修改

1.使用style的cssText

oDiv.style.cssText = 'padding:5px; border:1px solid #000; margin:5px;';

2.将这几个样式定义给一个类名,然后给标签添加类名

<style>

.pbm{

padding:5px;

border:1px solid #000;

margin:5px;

}

</style>

<script>

var oDiv = document.querySelector('.box');

oDiv.classList.add('pbm');

</script>

批量操作DOM

方法一:隐藏ul后,给ul添加节点,添加完成后再将ul显示

oUl.style.display = 'none';

for(var i=0;i<data.length;i++){

var oLi = document.createElement("li");

oLi.innerText = data[i].name;

oUl.appendChild(oLi);

}

oUl.style.display = 'block';

此时,在隐藏ul和显示ul的时候,触发了两次回流,给ul添加每个li的时候没有触发回流。

方法二:创建文档碎片,将所有li先放在文档碎片中,等都放进去以后,再将文档碎片放在ul中

文档碎片 - 虚拟标签,不会在页面中显示的,跟真的标签操作起来是一样的

varfragment=document.createDocumentFragment(); --- 创建文档碎片

for(var a = 0; a < 10; a++) {

var li = document.createElement('li')

li.innerText = a + 1

// ul.appendChild(li)

fg.appendChild(li)

}

ul.appendChild(fg)

ul.style.display = 'block'

文档碎片就是一个虚拟的DOM节点。对文档碎片操作不会造成回流。

方法三:将ul拷贝一份,将所有li放在拷贝中,等都放进去以后,使用拷贝替换掉ul

var newUl = ul.cloneNode(true)

for(var a = 0; a < 10; a++) {

var li = document.createElement('li')

li.innerText = a + 1

newUl.appendChild(li)

}

ul.parentElement.replaceChild(newUl, ul)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值