BOM和DOM


持续更新……

BOM

概念BOM(Brower Object Model)是浏览器对象模型。主要处理浏览器窗口和框架,描述与浏览器进行交互的方法和接口,可以对浏览器窗口进行访问和操作,比如弹出新的窗口、回退历史记录等。

BOM对象

  • Window JavaScript层级中的顶层对象,表示浏览器窗口。同时 window 也是网页中的全局对象。
  • Navigator代表当前浏览器的信息,通过该对象可以识别不同的浏览器。
  • History包含了浏览器窗口访问过的URL。
  • Location包含了当前URL的信息,通过 Location 可以获取地址栏信息,或者操作浏览器跳转页面。
  • Screen包含客户端显示屏的信息。

注意:这些 BOM 对象都是作为 window 对象的属性保存的,可以通过window对象来使用,也可以直接使用。比如,可以使用 window.location.href,也可以直接使用 location.href,二者是等价的。document也是在window中保存的

常用的对象

1、navigator

一般我们只会使用navigator.userAgent来获取浏览器的信息

代码示例如下:

<script>
        // 获取当前浏览器的userAgent
        var UA = navigator.userAgent;
        console.log('ramona当前浏览器的userAgent为:' + UA);

        if (/firefox/i.test(UA)) {
            alert('火狐浏览器');
        } else if (/chrome/i.test(UA)) {
            alert('Chrome浏览器');
        } else if (/msie/i.test(UA)) {
            alert('IE浏览器');
        } else if ('ActiveXObject' in window) {
            alert('IE 11 浏览器');
        }
    </script>

我们也可以直接在浏览器控制台上输入:navigator.userAgent,查看到如下结果:

查看浏览器信息

另外我们还可以在电脑上模拟移动端浏览器的场景。如下图方式操作:

浏览器配置1

浏览器配置2

不同浏览器的userAgent

iOS 版微信浏览器:

Mozilla/5.0 (iPhone; CPU iPhone OS 9_3 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13E233 MicroMessenger/6.3.15 NetType/WIFI Language/zh_CN

Android 版微信浏览器:

Mozilla/5.0 (Linux; Android 5.0.1; GT-I9502 Build/LRX22C; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/43.0.2357.121 Mobile Safari/537.36 MicroMessenger/6.1.0.78_r1129455.543 NetType/WIFI

iOS 版本QQ浏览器:

Mozilla/5.0 (iPhone; CPU iPhone OS 11_2_2 like Mac OS X) AppleWebKit/604.4.7 (KHTML, like Gecko) Mobile/15C202 QQ/7.3.5.473 V1_IPH_SQ_7.3.5_1_APP_A Pixel/1125 Core/UIWebView Device/Apple(iPhone X) NetType/WIFI QBWebViewType/1

Android 版 QQ浏览器:

Mozilla/5.0 (Linux; Android 4.4.2; PE-TL20 Build/HuaweiPE-TL20; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/043807 Mobile Safari/537.36 V1_AND_SQ_7.3.2_762_YYB_D QQ/7.3.2.3350 NetType/WIFI WebP/0.3.0 Pixel/1080

2、History

History对象可以用来操作浏览器的向前或向后翻页。

常见的属性和方法代码示例如下:

history.length  // 获取浏览器历史列表中的 url 数量,只是统计当次的数量,如果浏览器关了,数量会重置为1
history.back();  // 用来回退到上一个页面,作用和浏览器的「回退按钮」一样
history.forward();  // 用来跳转下一个页面,作用和浏览器的「前进按钮」一样
history.go( 1 ); // 向前跳转一个页面,相当于 history.forward()
history.go( 0 ); // 刷新当前页面
history.go( -1 ); // 向后跳转一个页面,相当于 history.back()

3、Location

Location 对象封装了浏览器地址栏的 URL 信息。

常见的属性和方法代码示例如下:

console.log(location.href); // 获取当前页面的url 路径
location.href = 'www.baidu.com'; // 跳转到指定的页面链接。通俗理解就是:跳转到其他的页面
location.assign(str);
location.reload(); // 重新加载当前页面
location.reload(true); // 在方法的参数中传递一个true,则会强制清空缓存刷新页面
 location.replace(); // 使用一个新的页面替换当前页面,调用完毕也会跳转页面。但不会生成历史记录,不能使用「后退按钮」后退

详情参考:https://github.com/huyaocode/webKnowledge/blob/master/%E5%89%8D%E7%AB%AF%E5%9F%BA%E7%A1%80/JS/BOM.md

DOM

概念:通俗的说DOM就是浏览器为JavaScript提供的一系列接口(通过window,document提供的),通过这些接口我们可以操作web页面。比如让盒子移动、变色、轮播图等。DOM不是编程语言,是文档对象模型,该模型独立于编程语言。

API (web 或 XML 页面) = DOM + JS (脚本语言)

节点

节点(Node):构成 HTML 网页的最基本单元。网页中的每一个部分都可以称为是一个节点,比如:html标签、属性、文本、注释、整个文档等都是一个节点。

虽然都是节点,但是实际上他们的具体类型是不同的。常见节点分为四类:

  • 文档节点(文档):整个 HTML 文档。整个 HTML 文档就是一个文档节点。

  • 元素节点(标签):HTML标签。

  • 属性节点(属性):元素的属性。

  • 文本节点(文本):HTML标签中的文本内容(包括标签之间的空格、换行)。

节点的类型不同,属性和方法也都不尽相同。所有的节点都是Object

DOM解析过程

HTML加载完毕,渲染引擎会在内存中把HTML文档,生成一个DOM树,getElementById是获取内中DOM上的元素节点。然后操作的时候修改的是该元素的属性在HTML当中,一切都是节点

DOM操作

1、创建新节点
方法 描述
createDocumentFragment() 创建一个 DOM 片段
createElement() 创建一个具体的元素
createTextNode() 创建一个文本节点
2、修改节点
方法 描述
appendChild() 添加子元素
removeChild() 删除子元素
replaceChild() 替换子元素
insertBefore() 插入子元素
cloneNode(true/false) 复制/克隆节点(不带参数/带参数false:只复制节点本身,不复制子节点;带参数true:既复制节点本身,也复制其所有的子节点)
3、DOM查找
元素节点的获取
方法 描述
getElementsByTagName() 通过标签名获取元素节点数组
getElementsByName() 通过元素的 Name 属性的值(IE 容错能力较强,会得到一个数组,其中包括 id 等于 name 值的)
getElementById() 通过元素 Id获取一个元素节点,唯一性
querySelector() 通过类名或元素Id (JQuery方法)
getElementsByClassName() 通过类名获取元素节点数组
访问关系的获取

JS中的父子兄访问关系:

属性 描述
节点.parentNode 获取父节点
节点.nextElementSibling || 节点.nextSibling 获取下一个兄弟节点
节点.previousElementSibling || 节点.previousSibling 获取前一个兄弟节点
节点自己.parentNode.children[index] 获得任意一个兄弟节点
节点.firstElementChild || 节点.firstChild 第一个子元素节点
节点.lastElementChild || 节点.lastChild 最后一个子元素节点
父节点.childNodes 获取所有子节点(标准属性。返回的是指定元素的子节点的集合)
父节点.children 获取所有子节点(非标准属性。返回的是指定元素的子元素节点的集合)
4、属性操作
属性/方法 描述
元素节点.属性名 / 元素节点[属性名] 获取节点的属性值
getAttribute() 获取属性
setAttribute() 设置属性
hasAttribute() 判断属性
removeAttribute() 移除属性
hasAttributes() 是否有属性设置
nodeType属性
  • nodeType == 1 表示的是元素节点(标签)。

  • nodeType == 2 表示是属性节点。

  • nodeType == 3 是文本节点。

nodeType、nodeName、nodeValue

我们那下面这个标签来举例:

<div id="box" value="111">hello</div>

上面这个标签就包含了三种节点:

  • 元素节点(标签)

  • 属性节点

  • 文本节点

获取这三个节点的方式如下:

    var element = document.getElementById("box1");  //获取元素节点(标签)
    var attribute = element.getAttributeNode("id"); //获取box1的属性节点
    var txt = element.firstChild;                   //获取box1的文本节点
    var value = element.getAttribute("id");         //获取id的属性值
    console.log(element); // <div id="box" value="111">hello</div>
    console.log(attribute); // id="box1"
    console.log(txt); // "hello"
    console.log(value); // box1

既然这三个都是节点,要想获取它们的nodeType、nodeName、nodeValue,代码如下:

    var element = document.getElementById("box1");  //获取元素节点(标签)
    var attribute = element.getAttributeNode("id"); //获取box1的属性节点
    var txt = element.firstChild;                   //获取box1的文本节点

    //获取nodeType
    console.log(element.nodeType);       //1
    console.log(attribute.nodeType);     //2
    console.log(txt.nodeType);           //3
    console.log("--------------");
    //获取nodeName
    console.log(element.nodeName);       //DIV
    console.log(attribute.nodeName);     //id
    console.log(txt.nodeName);           //#text
    console.log("--------------");
    //获取nodeValue
    console.log(element.nodeValue);     //null
    console.log(attribute.nodeValue);   //box1
    console.log(txt.nodeValue);         //生命壹号

innerHTML和innerText的区别

  • value:标签的value属性。

  • innerHTML:双闭合标签里面的内容(包含标签)。

  • innerText:双闭合标签里面的内容(不包含标签)。(老版本的火狐用textContent)

区别

获取内容:innerHTML会获取到标签本身,而innerText则不会

修改内容:innerHTML会修改标签本身,而innerText则不会

documen.write 和 innerHTML 的区别

  • document.write 只能重绘整个页面
  • innerHTML 可以重绘页面的一部分

innerHTML 与 outerHTML 的区别?

DOM 元素的 innerHTML, outerHTML, innerText, outerText 属性的区别也经常被面试官问到, 比如对于这样一个HTML元素:<div>content<br/></div>

  • innerHTML:内部HTML,content<br/>
  • outerHTML:外部HTML,<div>content<br/></div>
  • innerText:内部文本,content
  • outerText:内部文本,content

上述四个属性不仅可以读取,还可以赋值。outerTextinnerText 的区别在于 outerText 赋值时会把标签一起赋值掉,另外 xxText 赋值时HTML特殊字符会被转义。

jQuery的html()与innerHTML的区别?

jQuery的 .html() 会调用.innerHTML来操作,但是会捕获异常,然后用 .empty(), .append() 重新操作。 这是因为IE8中有些元素的 .innerHTML 是只读的。见:http://stackoverflow.com/questions/3563107/jquery-html-vs-innerhtml

Window 对象 与 document 对象

window
  • Window 对象表示当前浏览器的窗口,是 JavaScript 的顶级对象。
  • 我们创建的所有对象、函数、变量都是 Window 对象的成员。
  • Window 对象的方法和属性是在全局范围内有效的。
document
  • Document 对象是 HTML 文档的根节点与所有其他节点(元素节点,文本节点,属性节点, 注释节点)
  • Document 对象使我们可以通过脚本对 HTML 页面中的所有元素进行访问
  • Document 对象是 Window 对象的一部分,即 window.document

客户区坐标、页面坐标、屏幕坐标区别

客户区坐标:鼠标指针在可视区中的水平坐标(clientX)和垂直坐标(clientY)

页面坐标:鼠标指针在页面布局中的水平坐标(pageX)和垂直坐标(pageY)

屏幕坐标:设备物理屏幕的水平坐标(screenX)和垂直坐标(screenY)

mouseover/mouseout 与 mouseenter/mouseleave 的区别与联系

  1. mouseover/mouseout 是标准事件,所有浏览器都支持;mouseenter/mouseleave 是 IE5.5 引入的特有事件后来被 DOM3 标准采纳,现代标准浏览器也支持
  2. mouseover/mouseout 是冒泡事件;mouseenter/mouseleave不冒泡。需要为多个元素监听鼠标移入/出事件时,推荐 mouseover/mouseout 托管,提高性能
  3. 标准事件模型中 event.target 表示发生移入/出的元素,vent.relatedTarget对应移出/如元素;在老 IE 中 event.srcElement 表示发生移入/出的元素,event.toElement表示移出的目标元素,event.fromElement表示移入时的来源元素

focus/blur 与 focusin/focusout 的区别与联系

  1. focus/blur 不冒泡,focusin/focusout 冒泡
  2. focus/blur 兼容性好,focusin/focusout 在除 FireFox 外的浏览器下都保持良好兼容性,如需使用事件托管,可考虑在 FireFox 下使用事件捕获 elem.addEventListener(‘focus’, handler, true)

DOM事件

DOM 事件模型

先捕获,再到目标,再冒泡 。捕获是事件会从最外层开始发生,直到最具体的元素。冒泡是事件会从最内层的元素开始发生,一直向上传播,直到window对象。

事件模型

DOM 事件流

DOM 标准采用捕获+冒泡。两种事件流都会触发 DOM 的所有对象,从 window 对象开始,也在 window 对象结束。

DOM 标准规定事件流包括三个阶段:事件捕获阶段;处于目标阶段;事件冒泡阶段。

描述 DOM 事件捕获的具体流程

从 window -> document -> html -> body -> … -> 目标元素

Event 对象常见应用

event对象 描述
event.target 触发事件的元素
event.currentTarget 绑定事件的元素
event.preventDefault() 阻止默认行为(event.cancelBubble()和 event.preventBubble 都已经废弃)
event.stopPropagation() 阻止在捕获阶段或冒泡阶段继续传播,而不是阻止冒泡
event.stopImmediatePropagation() 阻止事件冒泡并且阻止相同事件的其他侦听器被调用。

事件的代理/委托

事件委托是指将事件绑定目标元素的到父元素上,利用冒泡机制触发该事件

优点

  • 可以减少事件注册,节省大量内存占用
  • 可以将事件应用于动态添加的子元素上

但使用不当会造成事件在不应该触发时触发

ulEl.addEventListener(
  "click",
  function (event) {
    var target = event.target || event.srcElement;
    if (target && target.nodeName.toUpperCase() === "LI") {
      console.log(target.innerHTML);
    }
  },
  false
);

自定义事件

  • Event
  • CustomEvent

CustomEvent 不仅可以用来做自定义事件,还可以在后面跟一个 object 做参数

var evt = new Event("myEvent");

someDom.addEventListener("myEvent", function () {
  //处理这个自定义事件
});

someDom.dispatchEvent(evt);
IE 的事件处理和 W3C 的事件处理有哪些区别?

绑定事件

  • W3C: targetEl.addEventListener(‘click’, handler, false);
  • IE: targetEl.attachEvent(‘onclick’, handler);

删除事件

  • W3C: targetEl.removeEventListener(‘click’, handler, false);
  • IE: targetEl.detachEvent(event, handler);

事件对象

  • W3C: var e = arguments.callee.caller.arguments[0]
  • IE: window.event

事件目标

  • W3C: e.target
  • IE: window.event.srcElement

阻止事件默认行为

  • W3C: e.preventDefault()
  • IE: window.event.returnValue = false’

阻止事件传播

  • W3C: e.stopPropagation()
  • IE: window.event.cancelBubble = true

参考:https://github.com/huyaocode/webKnowledge/blob/master/%E5%89%8D%E7%AB%AF%E5%9F%BA%E7%A1%80/JS/DOM.md

https://harttle.land/2015/10/01/javascript-dom-api.html

BOM 与 DOM 的关系

  1. javacsript 是通过访问 BOM 对象来访问、 控制、 修改浏览器
  2. BOM 的 window 包含了 document, 因此通过 window 对象的document 属性就可以访问、 检索、 修改文档内容与结构。
  3. document 对象又是 DOM 模型的根节点。

因此, BOM 包含了 DOM, 浏览器提供出来给予访问的是 BOM 对象, 从 BOM 对象再访 问到 DOM 对象, 从而 js 可以操作浏览器以及浏览器读取到的文档。


评论
评论
  目录