web前端-JS(DOMBOM)

Posted GY-93

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了web前端-JS(DOMBOM)相关的知识,希望对你有一定的参考价值。

web前端-JS(DOM、BOM)

1. DOM- 操作元素

  • DOM:文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可以扩展标记语言(html或则XML)的标准编程接口,W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式
  • DOM树:
  • 文档:第一个页面就是一个文档,DOM中使用document来表示
  • 元素:页面中的所有标签都是元素,DOM中使用element来表示
  • 节点:网页中的所有内容都是节点(标签、文本、属性、注释等),DOM中使用node来表示
  • 注意:DOM把以上内容都看做是对象

1.1 获取元素

DOM在我们实际开发中主要用来操作元素,那么我们如何获取页面中的元素?我们有如下几种方式获取:根据ID获取、根据标签名获取、通过HTML5新增的方法获取、特殊元素获取

  • getElementById():更具ID获取元素对象
  • element.getElementByTagName():返回带有指定标签名的对象的集合需要注意的是返回的一个对象的集合,如果需要操作里面的元素,需要便利,并且该方法得到的元素是动态的

注意:该方法获取页面中的元素都是以伪数组的方式返回([])如果没有该标签的元素, 那么返回是一个空的伪数组; 父元素必须是单个对象(必须指明是哪一个元素对象)获取的时候不包括父元素自己;

  • 通过HTML5新增的方法获取
    • document.getElementsByClassName('类名'):更具类名返回元素的对象集合
    • document.querySelector('选择器'):根据指定选择器来发挥第一个元素对象,注意:选择器需带表示,如: .div、#nav
    • document.querySelectorAll('选择器'):根据指定选择器返回所有的元素对象
  • 获取特殊元素:
    • document.body:获取body元素
    • document.doucmentElement:获取html对象

1.2 事件基础

事件由三部分组成,事件源、事件类型、事件处理程序,我们也称为事件的三要素。

常见的鼠标事件:

1.3 操作元素

javascript的DOM操作可以改变网页内容、结构和样,我们可以利用DOM操作元素来改变元素里面的内容、属性等。

1.3.1 改变元素的内容

  • element.innerText:从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉
  • element.innerHTML:起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行

    由上我们可以知道innerText会把元素里面的内容全部替换掉, 包括里面的子元素。上面div中的p元素在点击按钮之后,全部被产生的内容替换掉了,注意: innerText不识别html标签,非标准, 去除空格和换行


对于innerHTML属性,也会替换标签内所有内容,但是会保留空格和换行,并且能够识别html的标签

**注意:**两个属性都是可读写的, 可以获取元素里面的内容

1.3.2 常见元素的属性操作

  • src、href
  • id、alt、title
  • 修改src属性,达到修改背景图片的效果

1.3.3 表单元素的属性操作

利用DOM可以操作如下表单元素的属性:type、value、checked、selected、disabled

  • 密码框的隐藏显示

1.3.4 样式属性的操作

我们可以通过JS修改元素的大小、颜色、位置等样式。

  • element.style :行内样式操作
  • element.className:类名样式操作
  • 注意:
    • 如果样式修改较多,可以采用操作类名的方式更改元素样式
    • class因为是个保留字,因此使用className来操作元素类名属性
    • className 会直接更改元素的类名, 会覆盖原先的类名

通过style来修改元素样式

通过className修改元素样式

1.3.4.1 示例:当鼠标点击二维码关闭按钮的时候,则关闭整个二维码。


1.3.4.2 示例: 循环精灵图背景

1.3.4.3 示例:隐藏和显示文本框内容

1.3.4.4 密码框验证信息案例

1.3.4.5 示例: 百度换肤


1.3.5 操作元素总结

操作元素是DOM的核心内容:

1.3.6 自定义属性

1.3.6.1 自定义属性点的操作

  • 获取属性值:
    • element.属性:获取属性值(获取内置属性值,(元素本省自带属性)
    • element.getAttribute('属性')主要获取自定义的属性(标准)我们程序员自定义的属性
  • 设置属性值:
    • element.属性 = ’值‘:设置内置属性的值
    • element.setAttribute('属性','值'),主要是设置自定义属性的值(标准)
  • 移出自定义属性:element.removeAttribute('属性')

1.3.6.2 案例: tab切换按钮

当鼠标点击秀英的选项卡(tab),下面的内容会跟随内容的变化

1.3.6.3 H5自定义属性

自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中
自定义属性获取是通过getAttribute('属性')获取。但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。H5给我们新增了自定义属性:

  • 设置H5自定义属性:H5规定自定义属性data-开头作为属性名并且赋值。
    • 例如<div class="box" data-index="1"></div> , 或则使用JS设置element.setAttribute('data-index',2);
    • 兼容性获取element.getAttribute(data-index);
    • H5新增element.dataset.index或则element.dataset['index'],但是此种方式 ie11才开始支持

1.4 节点操作

1.4.1 节点概述

获取元素通常使用两种方式:

这两种方式都可以获取元素节点,我们后面都会使用,但是节点操作更简单

一般地至少拥有nodeType(节点类型)、nodeName(节点名称)、nodeValue(结点值)这三个基本属性

  • 元素节点的nodeType为1
  • 属性节点nodeType为2
  • 文本节点nodeType为3(文本节点包含文字、空格、换行等
  • 我们在实际开发中,节点操作主要操作的是元素节点

利用DOM树可以吧节点互粉为不同的层级关系,常见的是父子兄层级关系

1.4.2 父子节点

利用DOM树可以吧节点互粉为不同的层级关系,常见的是父子兄层级关系

  • 父级节点node.parentNode
    • parentNode :属性可返回某节点的父节点,注意是最近的一个父节点
    • 如果指定的结点没有父节点,则返回null
  • 子节点:parentNode.childNodes(标准)
    • parentNode.childNodes:返回包含指定结点的子节点的集合,该集合为即时更新的集合
    • 注意:返回值里面包含了所有的子节点,包含元素节点、文本节点等,如果只想要获取里面的元素节点,则需要专门处理,所以我们一般不提倡使用childNodes
    • parentNode.children(非标准):是一个只读属性,返回所有的子元素结点,它返回子元素结点。其余结点不返回(这个是我们需要重点掌握的),虽然children是一个非标准,但是得到了各个浏览器的支持,因此我们可以放心使用
  • 结点层级:
    • parentNode.firstChild:返回第一子节点,找不到则返回null,同样也包含所有的结点(不管是元素节点、文本节点都能识别)
    • parentNode.lastChild:返回最后一个子节点,找不到则返回null,同样,也包含所有的结点
    • parentNode.firstElementChild:返回第一个子元素结点,找不到则返回null注意:IE9以上才支持
    • parentNode.lastElementChild:返回最后一个子元素结点,找不到则返回null注意:IE9以上才支持

在实际的开发中,firstChildlastChild包含其它结点,操作不方便,而firstElementChildlastElementChild又有兼容性问题,那么我们如何获取第一个子元素结点或则最后一个子元素结点?

解决方案:如果想要第一个子元素结点,可以使用parentNode.children[0],最后一个结点则可以表示为:parentNode.children[parentNode.children.length-1]

案例: 下拉菜单

1.4.3 兄弟节点

  • node.nextSibling:返回当前元素的下一个兄弟结点,找不到则返回null同样,也包含所有的结点
  • node.previousSibling:返回当前元素上一个兄弟结点,找不到则返回null,同样,也是包含所有的结点
  • node.nextElementSibling:返回当前元素的下一个兄弟元素节点,找不到则返回null(IE9以上才支持
  • node.previousElementSibling:返回当前元素的上一个兄弟元素节点,找不到则返回nullIE9以上才支持

如果解决兼容性问题?可以自己封装一个兼容性函数。

1.4.4 创建和添加节点

  • document.createElement(‘tagName’):方法创建有tagName指定的HTML元素,因为这些元素原先不存在,是根据我们需求动态生成的,所以我们也称为动态创建元素节点
  • node.appendChild(child):将一个结点添加到置顶父节点的子节点列表末尾。类似于CSS里面的after伪元素
  • insertBefore(child, target):将一个结点添加到某个结点之前

    案例 :简单版发布留言案例

1.4.5 删除节点

  • node.removeChild(child):方法从DOM中删除一个子节点,返回删除的结点

案例: 删除留言案例

1.4.6 赋值节点(克隆节点)

  • node.cloneNode():返回调用该方法的结点的一个副本,也称为克隆结点/拷贝结点
  • 注意:
    • 如果括号参数为空或者为false,则是浅拷贝,即只是克隆赋值结点本身,不克隆里面的子节点
    • 如果括号内的参数为true,则是深度拷贝,会赋值结点本身以及里面所有的子节点

案例:动态生成表格

1.4.7三种动态创建元素区别

  • document.write():是直接将内容写入页面的内容流,但是文档流执行完毕时,则它会导致页面全部重绘
  • element.innerHTML:是讲内容写入某个DOM结点,不会导致页面全部重绘,并且如果是创建多个元素效率更高(不要拼接字符串,才去数组形式拼接)结构稍微复杂
  • createElement():创建多个元素效率稍低一点点,但是结构清晰
  • 总结:不同浏览器下,innerHTML效率要比createElement高


但是由我测试发现其实差别不是很大,时间几乎是相同的。可能由于课程的时间和本人学习的时间不一致,其中有一些更新。讲课中的时间差距还是蛮大的,但是现在测试发现没有什么差别。

2. DOM- 事件高级

2.1 注册事件

给元素添加事件,称为注册事件或则绑定事件。,注册事件的方式有两种,传统方式和方法监听注册方式


注意:传统的注册方式是没有兼容性问题的,但是事件监听的方式,同一个元素,同一个事件可以添加多个监听器

  • eventTarget.addEventListener():将指定的监听器注册到eventTargert(目标对象上)当该对象触发指定时间时,就回执行事件处理函数。(IE9才支持)该方法接收三个参数:
    • type :时间类型字符串,比如click,mouseover。注意这里不要带on
    • listener:事件处理函数,事件发生时,调用该监听函数
    • useCapture:可选参数,是一个布尔值,默认是false,学完DOM事件流后,在进一步学习
  • IE9之前是使用eventTarget.attachEvent(eventNameWithOn, callback),该方法是将指定的监听器注册到eventTarget(目标对象上),当该对象触发指定的事件时,指定的回调函数就会被执行.该方法接收两个参数:
    • eventNameWithOn :事件类型字符串,比如onclik、onmouserover,这里要带on
    • callback:事件处理函数,当目标触发事件时回调函数被调用

注册事件兼容性解决方案:(兼容处理的原则,首先照顾大多数浏览器,在处理特殊浏览器

2.2 删除事件

  • 删除事件的方式:
    • 删除传统注册事件方式: eventTarget.onClick= null
    • 删除方法监听注册方式:eventTarget.removeEventListener(type,listener,[useCapture])eventTarget.detachEvent(eventNameWithOn,calbback)

删除事件兼容性解决方案:

2.3 DOM事件流

  • 事件流:描述的是从页面中接收事件的顺序。事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程DOM事件流

比如我们给一个div注册了点击事件:

  • 事件冒泡:IE最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层结点的过程

  • 事件捕获:网景最早提出,由DOM最顶层结点开始,然后逐级像下传播到最具体的元素接收过程

  • 注意:

    • JS代码中能够执行捕获或则冒泡其中的一个阶段。
    • onclick和attachEvent只能得到冒泡阶段。
    • addEventListener(type,listener,[useCapture])第三个参数如果是true,表示在事件捕获阶段调用时间处理程序;如果是false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序
    • 实际开始中我们很少使用事件捕获,我们更关注事件冒泡
    • 有些事件是没有冒泡的,比如onblur、onfocus、onmouseover、onmouseleave
    • 事件冒泡有时候会带来麻烦,有些又会帮助很巧的做某些事件。后面会进一步学习

捕获阶段: 当我点击son(紫色盒子div)时, 控制台会输出如下打印信息,捕获路径:document->html->body->father->son, document和father也有监听对应的点击事件,所以也会触发

冒泡阶段:当我的监听方法,没有设置第三个参数时, 表示默认是在冒泡阶段。当我们点击son(紫色div)时,我们可以发现打印结果和上面的捕获阶段的打印结果刚好是相关的。冒泡的顺序:son->father->body->html->document

2.4 事件对象

2.4.1 事件对象基础


官方解释:event对象代表事件的状态,比如键盘按键的状态,鼠标的位置、鼠标按钮的状态。
简单理解:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event,它有很多属性和方法


这个event是个形参,系统帮我们设定为事件对象,不需要传递实参过去。
当我们注册事件时,event对象就会被系统自动创建,并以此传递给事件监听器(事件处理函数)

但是事件对象本身的获取存在兼容性问题:

  1. 在标准浏览器中是浏览器给方法传递的参数,只需要定义形参e就可以获取到。
  2. 在IE6~8中,浏览器不会给方法传递参数,如果需要的话,需要到window.event中获取查找。
  3. 解决:e = e || window.event;

  • 事件对象是我们事件的一系列先关数据的集合,跟事件相关的,比如鼠标点击里面包含了鼠标的先关信息,鼠标坐标啊,如果是键盘事件里面就包含的键盘事件的信息,比如判断用户按下了哪个键
  • 这个事件对象我们是可以自己命名的,,比如event、e
  • 事件对象的获取也是有兼容性问题的IE678通过window.event

2.4.2 target和this的区别

事件对象的常见属性和方法:

  • event.target:返回的是触发事件的对象(元素),也就是点击了哪个对象就返回哪个对象
  • this返回的是绑定事件的对象(元素),哪个元素绑定了该事件,就返回哪个元素。

    关于兼容性的问题:

2.4.3 阻止默认行为

2.5 阻止事件冒泡

  • 事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到DOM的最顶层结点
  • 事件冒泡的背身的特性,会带来的坏处,也会带来好处,需要我们灵活掌握。
  • 组织冒泡事件的两种方式:
    • 标准写法:利用事件对象里面的stopPropagation()方法
      *非标准写法:IE678利用事件对象的cancelBubble属性


阻止事件冒泡的的兼容性解决方案:

2.6 事件委托

  • 事件委托:事件委托也称为事件代理,在jQuery里面被称为事件委派。
  • 事件委托的原理不是每个子节点单独设置事件监听器,而是事件监听器设置在父节点上,然后利用冒泡员那里影响设置每个子节点。 上面案例:给ul注册点击事件,然后利用事件对象的target来找到当前点击的li,因为点击li,事件会冒泡到ul上,ul有注册事件,就会触发事件监听器。
  • 事件委托的作用:我们只操作了一次DOM,提高了程序的性能。

2.7 常用的鼠标事件

  • 常用的鼠标事件:
  • 进制鼠标右键菜单:contextmenu主要是控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
  • 禁止鼠标选中(selectstart 开始选中)

    鼠标事件对象: event对象代表事件的状态,跟事件相关的一系列信息的集合,现在阶段我们主要是用鼠标事件对象MouseEvent和键盘事件对象KeyboardEvent

2.8常用的键盘事件

事件除了使用鼠标触发,还可以使用键盘触发。

  • 注意:
    • 如果使用addEventListenter不需要加on
    • onkeypress和前面两个的区别的是,它不识别功能键,比如箭头、shift等
    • 三个事件的执行顺序:keyboard---keypress---keyup

键盘事件属性如下:

  • keyCode:返回该按键的ASCII值
  • key: 返回该按键的内容
  • 注意:onkeydown和onkeyup不区分字母的大小写,onkeypress区分字母的大小写。在我们实际的开发中,我们更过的使用onkeydown和onkeyup,它能识别所有的按键(包括功能键), 而onkeypress不识别功能键,但是keyCode属性能区分大小写,返回不同的ASCII值

案例:模拟京东搜索框(当键盘按下s键的时候,搜索框获得焦点)

案例:模拟京东快递单号查询案例
要求: 当我们在文本框输入内容时,文本框上面自动显示大号字体的内容

3. BOM 浏览器对象

3.1 BOM的概述

3.1.1 BOM的基础介绍

BOM(Browser Object Model)即浏览器对象,它提供了独立于内容而与浏览器窗口进行交互对象,其核心对象是window

BOM是由一系列的对象构成,并且每个对象都提供了很多方法与属性。

BOM缺乏标准,JavaScript语法的标准化组织是ECMA,DOM的标准化组织是W3C,BOM最初是Netscape浏览器标准的一部分

3.1.2 BOM的基本构成

window对象是浏览器的顶级对象,它具有双重角色

  1. 它是JS访问浏览器窗口的一个接口
  2. 它是一个全局对象,定义在全局作用域中的变量,函数都会变成widnow对象的属性和方法。

在调用的时候可以省略windown,前面学习的对话框都属于window对象方法,如alert(),prompt()等
注意:window下的一个特殊属性window.name

3.2 window对象常见事件

3.2.1 窗口加载事件- onload


window.onload是窗口(页面)加载事件,当文档内容完全家在完成会触发该事件(包括图像、脚本文件、CSS文件等)

  • 注意:
    • 有了window.onload就可以把JS代码写到页面元素上,因为onload是等页面内容全部加载完毕,在去执行处理函数
    • window.onload传统注册时间方式只能写一次,如果有多规格,会以最后一个window.onlaod为准
    • 如果使用addEventListener则没有限制


注意:onload函数不会收JS代码位置的影响, 当页面加载完成时, 就会回调这个方法。

3.2.2 窗口加载事件-DOMContentLoaded


DOMContentLoaded事件被触发时,仅当DOM加载完成时,不包括样式表,图片,flash等等
IE9以上才支持

如果页面的图片很多的话,从用户访问到onlaod触发可能小较长的时间,交互效果不能实现,必然影响用户的体验,此时用DOMContentLoaded事件比价合适。

3.2.3 调整窗口大小的事件-onresize


window.onresize:是调整窗口大小加载事件,当触发时就调用的处理函数

  • 注意:
    • 只要窗口大小发生像素变化,就回触发这个事件。
    • 我们经常利用这个事件完成响应式布局。window.innerWidth当前屏幕的宽度

3.3 定时器

window对象给我们提供了2个非常好用的方法-定时器setTimeout()setInterval()

3.3.1 setTimeout()定时器

window.setTimer(调用函数,[延迟的毫秒数]):该方法用于设置一个定时器,该定时器在定时器到期后执行调用函数,该定时器是单词执行的。第二个参数如果不传,默认是0 毫秒


如果页面中有很多个定时器,我们也可以给定时器加标识符(名字)

  • 注意:
    • window可以省略
    • 这个调用函数可以直接写函数,或则写函数名或则采用字符串函数名()三种形式,第三种不推荐
    • 延迟的毫秒数省略默认为0,如果写,必须是毫秒数
    • 因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。
  • window.clearTimeout(timeoutID):取消了先前通过调用setTimeout()建立的定时器,window也是可以省略的

3.3.2 setInterval()定时器

  • window.setInterval(回调函数,[间隔的毫秒数]):重复调用一个函数,每隔这个时间,就去调用一次回调函数。该定时器会重复回调。

  • window.clearInterval(intervalID):取消了先前通过调用setInterval()建立的定时器。

3.4 this指向问题

this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底是指向谁,一般情况下this的最终指向的是那个调用它的对象

3.5 JS中的同步和异步

3.5.1 同步和异步的概念

JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事情。这是因为JavaScript这门脚本语言诞生的使用所致–JavaScript是为处理页面中用户的交互,以及操作DOM而诞生的。比如我们对谋而DOM元素进行添加和删除操作,不能同时进行,应该进行添加,之后在删除。

单线程意味着,所有的任务都需要排队,前一个任务结束,才回执行后一个任务。这样所导致的问题是:如果JS的执行时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

以下代码的执行结果是什么?

为了解决这个问题 ,利用多核CPU的计算能力,HTML5提出Web Worker标准, 允许JavaScript脚本常见多个线程,于是,JS中出现了同步异步

  • 同步:前一个任务结束后在执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。
  • 异步:同事做多件事件。

看下面代码的执行结果:

3.5.2 JS执行机制

  • 同步任务:同步任务在主线程上执行,形成一个执行栈
  • 异步任务:JS的异步是通过回调函数实现的,一般而言,异步任务有一下三种类型
    • 普通事件,如click、resize
    • 资源加载:如load、error
    • 定时器,包括setInterval、setTimeout

异步任务相关回调函数添加到任务队列中(任务队列也称消息队列)

  • 先执行执行栈中的同步任务
  • 异步任务(回调函数)放入任务队列中。
  • 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行

3.5.3 事假循环


由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环(event loop)

3.6 location属性

3.6.1 lcoation属性介绍

window对象给我们提供了一个location属性用于获取或设置窗体的URL,并且可以用于解析URL。因为这个属性返回的是一个对象,所以我们将这个属性也称为location对象

  • URL: 统一资源定位符(Uniform Resource Locator, URL)是互联网上标准资源的地址,互联网上的每个文件都有一个唯一的URL,它包含的信息支出文件的位置以及浏览器应该怎么处理它。
    URL的一般语法格式为:

  • location对象的属性:

    注意:这里比较重要的是search、href

如何使用JS来实现页面的跳转:

3.6.2 案例: 获取URL中的参数

  • 案例:获取URL中的参数

  • location对象的方法:


3.7 navigator对象

navigator对象包含有关浏览器的信息,它有很多属性,我们最常用的就是userAgent,该属性可以返回由客户机发送服务器的user-agent头部的值

下面前端代码可以判断用户是由哪个终端打开页面,实现跳转

手机视图中navigator信息:

pc端navigator信息:

3.8 history对象

window对象给我们提供了一个history对象,与浏览器历史记录进行交互,该对象包含用户(在浏览器窗口中)

4.PC端网页特效

4.1 元素偏移量offset系列

4.1.1 offset的基础属性

  • offset翻译过来就是偏移量,我们使用offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等。
    • 获得元素距离带有定位父元素的位置
    • 获得元素自身的大小(宽度高度)
    • 注意:返回的数据都不带单位

offset的常用属性:

  • 没有定位父元素的情况:

  • 有定位父元素的情况:

4.1.2 offset和style的区别

案例: 获取鼠标在盒子内的坐标

案例:模态框拖拽

案例分析如下:

案例:仿进洞放大镜效果

4.2 元素的可视区client系列

client翻译过来就是客户度,我们使用client系列相关属性来获取元素可视区域的相关消息。通过client系列的相关属性可以动态的得到该元素的边框大小,元素大小等。

  • element.clientTop:返回元素上边距的大小
  • element.clientLeft:返回元素左边距的大小
  • element.clientWidth:返回自身包括padding、内容区的宽度,不含边框,返回数值不带单位
  • element.clientHeight:返回自身包括padding、内容区的高度,不含边框,返回数值不带单位

4.2.1 淘宝的flexible.js的源码分析

  • 立即执行函数:(function())() 或则 (function()())
// 立即执行函数也可以传递参数
(function (a , b)
    console(a+b);
)(1, 2)

立即执行函数最大的作用是独立创建了一个作用域里面所有的变量都是 局部变量,不会有命名冲突的情况

淘宝的flexible.js分析之核心原理

(function flexible(window, document) 
    // 获取的html 的根元素
    var docEl = document.documentElement
        // dpr 物理像素比
    var dpr = window.devicePixelRatio || 1

    // adjust body font size  设置我们body 的字体大小
    function setBodyFontSize() 
        // 如果页面中有body 这个元素 就设置body的字体大小
        if (document.body) 
            document.body.style.fontSize = (12 * dpr) + 'px'
         else 
            // 如果页面中没有body 这个元素,则等着 我们页面主要的DOM元素加载完毕再去设置body
            // 的字体大小
            document.addEventListener('DOMContentLoaded', setBodyFontSize)
        
    
    setBodyFontSize();

    // set 1rem = viewWidth / 10    设置我们html 元素的文字大小
    function setRemUnit() 
        var rem = docEl.clientWidth / 10
        docEl.style.fontSize = rem + 'px'
    

    setRemUnit()

    // reset rem unit on page resize  当我们页面尺寸大小发生变化的时候,要重新设置下rem 的大小
    window.addEventListener('resize', setRemUnit)
        // pageshow 是我们重新加载页面触发的事件
    window.addEventListener('pageshow', function(e) 
        // e.persisted 返回的是true 就是说如果这个页面是从缓存取过来的页面,也需要从新计算一下rem 的大小
        if (e.persisted) 
            setRemUnit()
        
    )

    // detect 0.5px supports  有些移动端的浏览器不支持0.5像素的写法
    if (dpr >= 2) 
        var fakeBody = document.createElement('body')
        var testElement = document.createElement('div')
        testElement.style.border = '.5px solid transparent'
        fakeBody.appendChild(testElement)
        docEl.appendChild(fakeBody)
        if (testE

以上是关于web前端-JS(DOMBOM)的主要内容,如果未能解决你的问题,请参考以下文章

Web APIs(DOMBOM)综述

Web APIs(DOMBOM)综述

JS DOMBOM事件常见面试题分析

20.【Web API】——移动端网页特效(2020-09-13)

web前端练习22----js中的原型对象prototype,原型链(重要)

web前端课程技术内容之如何做一个简单的手机端页面的翻页