从零开始学习BOM&DOM

前言

ECMAScript,描述了该语言的语法和基本对象,如类型、运算、流程控制、面向对象、异常等。

文档对象模型(DOM),描述处理网页内容的方法和接口。

浏览器对象模型(BOM),描述与浏览器进行交互的方法和接口。

DOM/BOM架构

image

概述

JavaScript运行在浏览器

BOM就是连接JavaScript代码和浏览器的桥梁,而DOM就是用来操作各种标签元素的。

  • BOM包括 window、history、location、document ...
  • DOM包括 Document(整个文档)、Element(标签元素)、CharacterData(字符数据)、Attr(属性),这些元素又可以继续往下划分。

    • Document 又可以分为HTMLDocument(就是我们定义的html文件)和XMLDocument(XML文件,安卓会用,前端用不到)

    • Element 可以划分为 HTMLElement(表示 HTML 中的一个元素,比如div),HTMLElement又可以划分为HTMLDIvElement 和 HTMLImageElement 故名思义

    • CharacterData 可以划分为text(text标签)和Comment(注释)

    • Attr 可以理解我们元素的class属性id属性以及值

继承关系

  • 其中DOM元素、window对象都继承自EventTarget,所以它们都有EventTarget上的实例方法而document是HTMLDocument的实例对象
  • 所以window上是可以绑定事件,监听事件,分发事件的
  • 其中DOM 中的所有元素节点都继承自EventTarget接口,所以DOM中任意节点可以绑定事件,监听事件,分发事件

我们可以在浏览器中打印它的原型属性

通过下图我们可以看出,window继承Window,Window继承自EventTarget

image

通过下图我们可以看出,document继承HtmlDocument,HtmlDocument继承自Document,Document继承自Node节点,Node节点继承自EventTarget

image

顺便说一句:EventTarget继承自Object,Object继承自null

EventTarget 接口

EventTarget 是一个 DOM 接口,由可以接收事件、并且可以创建侦听器的对象实现。

Elementdocumentwindow 是最常见的 event targets

EventTarget有三个原型方法,在window和DOM元素上都可以使用

  • addEventListener 给元素绑定事件

  • removeEventListener 移除元素绑定的事件

  • dispatchEvent 派发事件

BOM

认识BOM

  • JavaScript有一个非常重要的运行环境就是浏览器,而且浏览器本身又作为一个应用程序需要对其本身进行操作,所以通常浏览器会有对 应的对象模型(BOM,Browser Object Model)。
  • BOM主要包括一下的对象模型:

    • window:包括全局属性、方法,控制浏览器窗口相关的属性、方法;

    • location:浏览器连接到的对象的位置(URL);

    • history:操作浏览器的历史;

    • document:当前窗口操作文档的对象;

  • window对象在浏览器中有两个身份:

    • 身份一:全局对象。我们知道ECMAScript其实是有一个全局对象的,这个全局对象在Node中是global;在浏览器中就是window对象;

    • 身份二:浏览器窗口对象。作为浏览器窗口时,提供了对浏览器操作的相关的API;

Window全局对象

在浏览器中,window对象就是之前经常提到的全局对象

  • 比如在全局通过var声明的变量,会被添加到全局环境变量中,也就是会被添加到window上;
  • 比如window默认给我们提供了全局的函数和类:setTimeout、Math、Date、Object等;
var message = 'hello'
function foo(){
    console.log("foo")
}
console.log(window.message)
window.foo()

 window.setTimeout(()=>{
     console.log('setTimout')
 })
 
 const obj = new window.Object()
 console.log(obj)

Window窗口对象

window是一个复杂的大对象,包含了大量的对象和方法

  • 第一:包含大量的属性,localStorage、console、location、history、screenX、scrollX等等(大概60+个属性);

  • 第二:包含大量的方法,alert、close、scrollTo、open等等(大概40+个方法);

  • 第三:包含大量的事件,focus、blur、load、hashchange等等(大概30+个事件);

  • 第四:包含从EventTarget继承过来的方法,addEventListener、removeEventListener、dispatchEvent方法;

参考地址:MDN文档:developer.mozilla.org/zh-CN/docs/…

[图片上传失败...(image-bb8cd9-1676958099638)]

常见的属性

// screenX和screenY属性返回窗口相对于屏幕的X和Y坐标。
console.log(window.screenX)
console.log(window.screenY)

// 监听滚动
window.addEventListener("scroll", () => {
   console.log(window.scrollX, window.scrollY)
})
// 获取窗口的宽度与高度:
console.log(window.outerHeight)
console.log(window.innerHeight)

常见的方法

const scrollBtn = document.querySelector("#scroll")
scrollBtn.onclick = function() {
    //1.scrollTo
    window.scrollTo({ top: 2000 })

    //2.close
    window.close()

    // 3.open
    window.open("http://www.baidu.com", "_self")
}

常见的事件

// 整个页面以及所有资源加载完成
window.onload = function() {
  console.log("window窗口加载完毕~")
}

window.onfocus = function() {
  console.log("window窗口获取焦点~")
}

window.onblur = function() {
  console.log("window窗口失去焦点~")
}

//hash 改变
const hashChangeBtn = document.querySelector("#hashchange")
hashChangeBtn.onclick = function() {
  location.hash = "aaaa"
}
window.onhashchange = function() {
  console.log("hash发生了改变")
}

Navigator 对象

Navigator 对象包含有关浏览器的信息。到底提供哪些信息很大程度取决于用户的浏览器,但是也有一些公共的属性,如userAgent 存在所有的浏览器中

Navigator 对象常见的属性

window.navigator.appCodeName
//返回浏览器的代码名   'Mozilla'
window.navigator.appName
//返回浏览器的名称 'Netscape'
window.navigator.appVersion
//返回浏览器的平台和版本信息
//'5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1'
window.navigator.cookieEnabled
//返回指明浏览器中是否启用 cookie 的布尔值 true
window.navigator.platform
//返回运行浏览器的操作系统平台 'MacIntel'
window.navigator.userAgent
//返回由客户机发送服务器的user-agent 头部的值
//'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36'

使用场景

检测插件

可以检测浏览器内是否安装了特定的插件

navigator.plugins

判断系统类型,版本信息

location对象

location 对象 是最有用的BOM对象之一

它既是window对象的属性,也是document对象的属性,window.location 和document.location引用的是同一个对象。

常见属性

  • href: 当前window对应的超链接URL, 整个URL;
  • protocol: 当前的协议;
  • host: 主机地址;
  • hostname: 主机地址(不带端口);
  • port: 端口;
  • pathname: 路径;
  • search: 查询字符串;
  • hash: 哈希值;
  • username:URL中的username(很多浏览器已经禁用);
  • password:URL中的password(很多浏览器已经禁用);

常用方法

  • assign:赋值一个新的URL,并且跳转到该URL中;
  • replace:打开一个新的URL,并且跳转到该URL中(不同的是不会在浏览记录中留下之前的记录);
  • reload:重新加载页面,可以传入一个Boolean类型;如果把该方法的参数设置为 true,那么无论文档的最后修改日期是什么,它都会绕过缓存,从服务器上重新下载该文档。
location.assign("http://www.baidu.com")
location.href = "http://www.baidu.com"

location.replace("http://www.baidu.com")
location.reload(false)

Screen对象

在编程中使用不多,只用来表明客户端的能力,其中包括浏览器窗口外部的显示器的信息,如像素的宽度和高度,每个浏览器的screen对象都包含着不同的属性。根据具体业务场景去查询就好。

history 对象

history对象允许我们访问浏览器曾经的会话历史记录。

history对象有两个属性

  • length:会话中的记录条数;
  • state:当前保留的状态值;

history对象有五个方法:

  • back():返回上一页,等价于history.go(-1);
  • forward():前进下一页,等价于history.go(1);
  • go():加载历史中的某一页;
  • pushState():打开一个指定的地址;
  • replaceState():打开一个新的地址,并且使用replace;

总结

BOM 以window对象为依托,表示浏览器窗口以及页面可见区域

DOM

document Object Model 文档对象模型

节点层次

DOM可以把任何HTML和XML文档描绘成一个由多层节点构成的树形结构。

<html>
  <head>
    <meta charset="UTF-8">
    <title>测试</title>
  </head>
  <body>
    <h1>标题</h1>
    <ul>
      <1i>
        <a href="#">链接</a>
      </1i>
    </ul>
  </body>
</html>
image

上图中就包括DOM的主要节点

Document文档节点

表示整个 HTML 页面(相当于 document 对象)

当需要访问任何标签、属性或文本时,都可以通过文档节点进行导航

Element元素节点 ul h1 li

表示 HTML 页面中的标签(即 HTML 页面的结构)

当访问 DOM 树时,需要从查找元素节点开始

Attr 属性节点 href

表示 HTML 页面中的开始标签包含的属性

Text 文本节点 比如title的内容


Node 类型

所有的DOM节点类型都继承自Node接口,每个节点都有一个nodeType属性,用于表明节点的类型。

对于HTML文档,节点主要有以下六种类型:Document节点、DocumentType节点、Element节点、Attribute节点、Text节点和DocumentFragment节点。

分类

节点 名称 含义
Document 文档节点 整个文档(window.document)
DocumentType 文档类型节点 文档的类型(比如 'DOCTYPE html')
Element 元素节点 HTML元素(比如body、a等)
Attribute 属性节点 HTML元素的属性(比如class="right")
Text 文本节点 HTML文档中出现的文本
DocumentFragment 文档碎片节点 文档的片段

常用属性

Node 有几个非常用且重要的属性

  • nodeName:node节点的名称;
  • nodeType:可以区分节点的类型;
  • nodeValue:node节点的值;
  • childNodes:所有的子节点;

Document 类型

JavaScript 通过Document 类型表示整个文档。

Document 类型可以表示 HTML 页面或者 其他基于 XML 的文档。不过最常用的应用还是作为HTMLDocument实例的document 对象。

在浏览器中 document 对象是 HTMLDocument的一个实例,表示整个HTML页面。而且,document对象也是window对象的一个属性,因此可以作为全局对象来访问。

常见属性

  • document.body 返回文档的body元素
  • document.title 返回当前文档的标题
  • document.head 返回当前文档的head内容
  • document.children[0] 返回当前文档html内容

常见方法

  • 创建元素
  • 获取标签元素
// 创建元素
const imageEl = document.createElement("img")
const imageEl2 = new HTMLImageElement()

// 获取元素
const divEl1 = document.getElementById("box")
const divEl2 = document.getElementsByTagName("div")
const divEl3 = document.getElementsByName("title")
  • 文档写入

将输出流写入到网页的能力。

document.write()
document.writeln()
document.open()
document.close()

Element 类型

Element 类型用于表现XML和HTML元素,提供了对元素标签名,子节点及特性的访问

我们平时创建的div、p、span等元素在DOM中表示为Element元素

常见属性

  • 子元素 children childNodes
  • tagName
  • id/class
  • clientWidth/clientHeight
  • clientLeft/clientTop
  • offsetLeft/offsetTop

常见方法

获取特性 getAttribute 修改某个特性 setAttribute

创建元素 document.createElement()

Text 类型

文本节点由Text类型表示,包含的是可以照字面解释的纯文本内容

  • 创建文本节点:document.createTextNode()

Comment 类型

注释

DocumentFragment 类型

DOM规定文档片段是一种轻量级的文档,不会像完整的文档那样占有额外的资源

可以在里面保存将来会添加到文档的节点。要创建文档片段,可以使用document.createDocumentFragment()

文档片段本身永远不会成为文档树的一部分

Attr类型

元素的特性在DOM中用Attr类型来表示。很少使用。

总结

DOM1级将HTML和XML文档看作一个层次化的节点树,方便js来直接操作。

DOM 是由各种节点构成的

  • 最基本节点是Node,所有的节点都继承自Node
  • Document 表示整个文档
  • Element 表示文档中的HTML 或者XML 元素

DOM扩展

对DOM的扩展主要包括 选择符API 和 HTML5

选择符API

选择符,最核心的两个API 就是 querySelector() 和 querySelectorAll()

可以通过Document 和 Element 类型的实例调用

const divEl1 = document.querySelector(".content")
const divEl2 = document.querySelectorAll(".content")

HTML5

html5涉及的面非常广,我们这里这讨论与DOM 节点相关的内容

获取dom元素

  • getElementsByClassName() 可以通过document 对象和所有HTML元素调用该方法,查询一个或者包含类名的字符串

自定义数据属性

可以为元素添加非标准的属性,但是要添加前缀 data-

通过元素的 dataset 属性来访问自定义的属性的值

<div id ="myDiv" data-appId = "12345" data-name="yz"></div>

var div = document.getElementById('myDiv')

var appId = div.dataset.appId
var name = div.dataset.name

插入标记

innerHTML属性

  • 可以获取调用元素的所有子节点对应的html片段
  • 可以是根据指定的值创建DOM树,替换原有的元素节点

一般我们插入大量新HTML标记时,使用innerHTML 与通过多次DOM操作先创建节点再指定它们之间的关系相比,效率更高,因为在设置innerHTML 时就会先创建一个HTML解析器,这个解析是在浏览器级别的基础上代码(c++)运行的,因此比执行js 快得多,当然也会带来 创建销毁 html 解析器也有性能消耗。所以控制次数。

DOM2和DOM3

DOM1级主要定义的是HTML和XML文档的底层结构

DOM2级和DOM3级是在这个结构基础上引入了更多的交互能力和特性。扩展了DOM API,以满足操作DOM的所有需求,同时提供更好的错误处理和特性监测能力

DOM变化

  • Node 类型 Document 类型 Element 类型 增加了命名空间的概念
  • DOM3引入 两个辅助比较节点的方法 isSameNode() 和 isEqualNode( )
-   一个判断相同 两个节点引用的是同一个对象
-   一个判断相等 两个节点是同类型的对象,具有相等的属性(nodeName,nodeValue等等),而且他们的attributes和 childNodes属性也相等(相同位置包含相同的)
var div1 = document.createElement("div")
div1.setAttribute("class","box")

var div1 = document.createElement("div")
div1.setAttribute("class","box")

alert(div1.isSameNode(div1)) // true
alert(div1.isEqualNode(div1)) // true
alert(div1.isSameNode(div2)) // false
  • iframe中的文档对象可以通过contentDocument 访问 所有浏览器都支持
var iframe = document.getElementById("myIframe")
var iframe = iframe.contentDocuemnt || iframe.contentWindow.document

样式变化

访问元素的样式

  • 新增style属性 可以通过style对象访问所有样式信息,也可以进行修改
  • document.default.getComputedStyle(dom) 可以返回整个dom的样式

操作样式表

  • 大多数情况下,使用style属性就可以满足所有操作样式柜子的需求

元素大小

  • 偏移量
    • offsetHeight offsetWdith offsetLeft offsetTop
    • 可以通过以上四个属性计算
  • 客户区大小
    • clientHeight clientWidth
  • 滚动大小
    • scrollHeight scrollWidth scrollLeft scrollTop
    • scrollLeft scrollTop可以用来确定当前元素滚动状态
image
  • 确定元素大小

    • getBoundClientRect()返回一个矩形对象,包含四个属性 left top right bottom,给出了元素在页面中相对于视口的位置。
    • top/y:元素上边到视窗上边的距离;
    • right:元素右边到视窗左边的距离;
    • bottom:元素下边到视窗上边的距离;
    • left/x:元素左边到视窗左边的距离;
    • width:元素的宽度;
    • height:元素的高度;
image

范围

为了让开发人员更方便得控制页面,dom2 定义了范围 range接口。

document.createRange()

  • 用dom范围实现简单选择
var range1 = document.createRange()
var p1 = document.getElementById('p1')

range1.selcetNode(p1)
  • 也可以操作修改dom范围中的内容

小结

dom2 级主要新增了操作样式的能力和操作范围内dom的能力

总结

对于dom和bom的学习,我所秉持的观点依然是,抓大放小,建立知识体系,常用的api可以了解,不常用的api知道去哪里查就好,因为平常业务开发也接触不到太底层的代码。

框架发展到今天,对我们前端开发来说,已经很少去操作Dom了,但框架已经帮助我们做了,对于Bom的交互也有很多封装成熟的函数库,但是如果要对前端深入学习,我觉得这些知识还是必须掌握的,前端学习js 永远是基础,框架函数库,都是锦上添花的东西。

我们要知其然,更要知其所以然。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容