DOM和BOM

DOM: 文档对象模型( Document Object Model
  • 简称 DOM,将页面所有的内容表示为可以修改的对象
BOM: 浏览器对象模型( Browser Object Model
  • 简称 BOM,由浏览器提供的用于处理文档(document)之外的所有内容的其他对象
  • 比如navigatorlocationhistory等对象;

DOM

DOM相当于是JavaScript和HTML、CSS之间的桥梁 通过浏览器提供给我们的DOM API,我们可以对元素以及其中的内容做任何事情;

 对于最顶层的html、head、body元素,我们可以直接在document对象中获取到:

  • html元素:<html> = document.documentElement
  • body元素:<body> = document.body
  • head元素:<head> = document.head
  • 文档声明:<!DOCTYPE html> = document.doctype

如果我们获取到 一个节点(Node) 后,可以根据 这个节点去获取其他的节点 ,我们称之为 节点之间的导航
节点之间存在如下的关系:
  • 父节点:parentNode
  • 前兄弟节点:previousSibling
  • 后兄弟节点:nextSibling
  • 子节点:childNodes
  • 第一个子节点:firstChild
  • 第二个子节点:lastChild

如果我们获取到一个 元素(Element) 后,可以根据 这个元素去获取其他的元素 ,我们称之为 元素之间的导航
节点之间存在如下的关系:
  • 父元素:parentElement
  • 前兄弟节点:previousElementSibling
  • 后兄弟节点:nextElementSibling
  • 子节点:children
  • 第一个子节点:firstElementChild
  • 第二个子节点:lastElementChild

DOM为我们提供了获取元素的方法: 

开发中如何选择呢?
  • 目前最常用的是querySelectorquerySelectAll
  • getElementById偶尔也会使用或者在适配一些低版本浏览器时;

节点属性

nodeType属性:
  • nodeType 属性提供了一种获取节点类型的方法;
  • 它有一个数值型值(numeric value);
nodeName:获取node节点的名字;  
tagName:获取元素的标签名词;

tagName nodeName 之间有什么不同呢?
tagName 属性仅适用于 Element 节点;
nodeName 是为任意 Node 定义的:
  • 对于元素,它的意义与 tagName 相同,所以使用哪一个都是可以的;
  • 对于其他节点类型(textcomment 等),它拥有一个对应节点类型的字符串;

nodeValue/data 属性

  • 用于获取非元素节点的文本内容

  

innerHTML 属性
  • 将元素中的 HTML 获取为字符串形式;
  • 设置元素中的内容;
outerHTML 属性
  • 包含了元素的完整 HTML
  • innerHTML 加上元素本身一样;
textContent 属性
  • 仅仅获取元素中的文本内容;
innerHTML和textContent的区别:
  • 使用 innerHTML,我们将其“作为 HTML”插入,带有所有 HTML 标签。
  • 使用 textContent,我们将其“作为文本”插入,所有符号(symbol)均按字面意义处理。

hidden属性:也是一个全局属性,可以用于设置元素隐藏。

DOM 元素还有其他属性:

value
  • <input>,<select> 和 <textarea>(HTMLInputElement,HTMLSelectElement……)的 value。
href
  • <a href="...">(HTMLAnchorElement)的 href。
id
  • 所有元素(HTMLElement)的 “id” 特性(attribute)的值。

元素的属性和特性 

浏览器在解析HTML元素时,会将对应的attribute也创建出来放到对应的元素对象上。

  • 比如id、class就是全局的attribute,会有对应的id、class属性
  • 比如href属性是针对a元素的,type、value属性是针对input元素的;
属性attribute的分类:
  • 标准的attribute:某些attribute属性是标准的,比如id、class、href、type、value等;
  • 非标准的attribute:某些attribute属性是自定义的,比如abc、age、height等;

对于所有的attribute访问都支持如下的方法:

  • elem.hasAttribute(name) — 检查特性是否存在。
  • elem.getAttribute(name) — 获取这个特性值。
  • elem.setAttribute(name, value) — 设置这个特性值。
  • elem.removeAttribute(name) — 移除这个特性。
  • attributes:attr对象的集合,具有name、value属性;
attribute具备以下特征:
  • 它们的名字是大小写不敏感的(id 与 ID 相同)。
  • 它们的值总是字符串类型的。

对于标准的attribute,会在DOM对象上创建与其对应的property属性 

在大多数情况下,它们是相互作用的
  • 改变property,通过attribute获取的值,会随着改变;
  • 通过attribute操作修改,property的值会随着改变;
  • 但是input的value修改只能通过attribute的方法;
除非特别情况,大多数情况下,设置、获取attribute,推荐使用property的方式:
  • 这是因为它默认情况下是有类型的;

 

前面我们有学习HTML5的data-*自定义属性,那么它们也是可以在dataset属性中获取到的:

 

有时候我们会通过JavaScript来动态修改样式,这个时候我们有两个选择:
  • 选择一:在CSS中编写好对应的样式,动态的添加class
  • 选择二:动态的修改style属性
开发中如何选择呢?
  • 在大多数情况下,如果可以动态修改class完成某个功能,更推荐使用动态class
  • 如果对于某些情况,无法通过动态修改class(比如精准修改某个css属性的值),那么就可以修改style属性

元素的class attribute,对应的property并非叫class,而是className

  • 这是因为JavaScript早期是不允许使用class这种关键字来作为对象的属性,所以DOM规范使用了className
  • 虽然现在JavaScript已经没有这样的限制,但是并不推荐,并且依然在使用className这个名称; 

我们可以对className进行赋值,它会替换整个类中的字符串。 

 

如果我们需要添加或者移除单个的class,那么可以使用classList属性。
elem.classList 是一个特殊的对象:
  • elem.classList.add (class) :添加一个类
  • elem.classList.remove(class):添加/移除类。
  • elem.classList.toggle(class) :如果类不存在就添加类,存在就移除它。
  • elem.classList.contains(class):检查给定类,返回 true/false。
classList是 可迭代对象 ,可以通过 for of 进行遍历。
如果需要单独修改某一个CSS属性,那么可以通过style来操作:
  • 对于多词(multi-word)属性,使用驼峰式 camelCase

如果我们将值设置为 空字符串 ,那么会使用 CSS的默认样式
多个样式的写法,我们需要使用 cssText属性

  

  • 不推荐这种用法,因为它会替换整个字符串;
如果我们需要读取样式:
  • 对于内联样式,是可以通过style.*的方式读取到的;
  • 对于style、css文件中的样式,是读取不到的;
这个时候,我们可以通过 getComputedStyle 的全局函数来实现:

 

前面我们使用过 document.write 方法写入一个元素:
  • 这种方式写起来非常便捷,但是对于复杂的内容、元素关系拼接并不方便
  • 它是在早期没有DOM的时候使用的方案,目前依然被保留了下来;
那么目前我们想要插入一个元素,通常会按照如下步骤:
  • 步骤一:创建一个元素;
  • 步骤二:插入元素到DOM的某一个位置;
创建元素: document.createElement(tag)

插入元素的方式如下:
  • node.append(...nodes or strings) —— 在 node 末尾 插入节点或字符串,
  • node.prepend(...nodes or strings) —— 在 node 开头 插入节点或字符串,
  • node.before(...nodes or strings) —— 在 node 前面 插入节点或字符串,
  • node.after(...nodes or strings) —— 在 node 后面 插入节点或字符串,
  • node.replaceWith(...nodes or strings) —— 将 node 替换为给定的节点或字符串。

移除元素我们可以调用元素本身的remove方法:
如果我们想要复制一个现有的元素,可以通过cloneNode方法:
  • 可以传入一个Boolean类型的值,来决定是否是深度克隆
  • 深度克隆会克隆对应元素的子元素,否则不会;

在很多地方我们也会看到一些旧的操作方法:

parentElem.appendChild(node)
  • 在parentElem的父元素最后位置添加一个子元素
parentElem.insertBefore(node, nextSibling)
  • 在parentElem的nextSibling前面插入一个子元素;
parentElem.replaceChild(node, oldChild)
  • 在parentElem中,新元素替换之前的oldChild元素;
parentElem.removeChild(node)
  • 在parentElem中,移除某一个元素;

元素的大小、滚动
  • clientWidth:contentWith+padding(不包含滚动条)
  • clientHeight:contentHeight+padding
  • clientTop:border-top的宽度
  • clientLeft:border-left的宽度
  • offsetWidth:元素完整的宽度
  • offsetHeight:元素完整的高度
  • offsetLeft:距离父元素的x
  • offsetHeight:距离父元素的y
  • scrollHeight:整个可滚动的区域高度
  • scrollTop:滚动部分的高度

window的大小、滚动

  • innerWidthinnerHeight:获取window窗口的宽度和高度(包含滚动条)
  • outerWidthouterHeight:获取window窗口的整个宽度和高度(包括调试工具、工具栏)
  • documentElement.clientHeightdocumentElement.clientWidth:获取html的宽度和高度(不包含滚动条)
window的滚动位置:
  • scrollX:X轴滚动的位置(别名pageXOffset)
  • scrollY:Y轴滚动的位置(别名pageYOffset)
也有提供对应的滚动方法:
  • 方法 scrollBy(x,y) :将页面滚动至 相对于当前位置的 (x, y) 位置;
  • 方法 scrollTo(pageX,pageY) 将页面滚动至 绝对坐标;

BOM

JavaScript有一个非常重要的运行环境就是浏览器
  • 而且浏览器本身又作为一个应用程序需要对其本身进行操作;
  • 所以通常浏览器会有对应的对象模型(BOM,Browser Object Model);
  • 我们可以将BOM看成是连接JavaScript脚本与浏览器窗口的桥梁;
BOM主要包括以下的对象模型:
  • window:包括全局属性、方法,控制浏览器窗口相关的属性、方法;
  • location:浏览器连接到的对象的位置(URL);
  • history:操作浏览器的历史;
  • navigator:用户代理(浏览器)的状态和标识(很少用到);
  • screen:屏幕窗口信息(很少用到)
window对象在浏览器中可以从两个视角来看待:
视角一:全局对象。
  • 我们知道ECMAScript其实是有一个全局对象的,这个全局对象在Node中是global
  • 在浏览器中就是window对象
视角二:浏览器窗口对象。
  • 作为浏览器窗口时,提供了对浏览器操作的相关的API
当然,这两个视角存在大量重叠的地方,所以不需要刻意去区分它们:
  • 事实上对于浏览器和Node中全局对象名称不一样的情况,目前已经指定了对应的标准,称之为globalThis,并且大多数现代浏览器都支持它;
  • 放在window对象上的所有属性都可以被访问;
  • 使用var定义的变量会被添加到window对象中;
  • window默认给我们提供了全局的函数和类:setTimeout、Math、Date、Object等;  
事实上window对象上肩负的重担是非常大的:
  • 第一:包含大量的属性,localStorage、console、location、history、screenX、scrollX等等(大概60+个属性);
  • 第二:包含大量的方法,alert、close、scrollTo、open等等(大概40+个方法);
  • 第三:包含大量的事件,focus、blur、load、hashchange等等(大概30+个事件);
  • 第四:包含从EventTarget继承过来的方法,addEventListener、removeEventListener、dispatchEvent方法;

查看MDN文档时,我们会发现有很多不同的符号,这里我解释一下是什么意思:
  • 删除符号:表示这个API已经废弃,不推荐继续使用了;
  • 点踩符号:表示这个API不属于W3C规范,某些浏览器有实现(所以兼容性的问题);
  • 实验符号:该API是实验性特性,以后可能会修改,并且存在兼容性问题;

 

 

location对象用于表示window上当前链接到的URL信息。
常见的属性有哪些呢?
  • href: 当前window对应的超链接URL, 整个URL;
  • protocol: 当前的协议;
  • host: 主机地址;
  • hostname: 主机地址(不带端口);
  • port: 端口;
  • pathname: 路径;
  • search: 查询字符串;
  • hash: 哈希值;
  • username:URL中的username(很多浏览器已经禁用);
  • password:URL中的password(很多浏览器已经禁用);
我们会发现location其实是URL的一个抽象实现:

location有如下常用的方法:
  • assign:赋值一个新的URL,并且跳转到该URL中;
  • replace:打开一个新的URL,并且跳转到该URL中(不同的是不会在浏览记录中留下之前的记录);
  • reload:重新加载页面,可以传入一个Boolean类型;

URLSearchParams 定义了一些实用的方法来处理 URL 的查询字符串。
  • 可以将一个字符串转化成URLSearchParams类型;
  • 也可以将一个URLSearchParams类型转成字符串;
URLSearchParams常见的方法有如下:
  • get:获取搜索参数的值;
  • set:设置一个搜索参数和值;
  • append:追加一个搜索参数和值;
  • has:判断是否有某个搜索参数;
中文会使用 encodeURIComponent decodeURIComponent 进行编码和解码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值