JavaScript 操作 DOM 总结
基本概念
DOM 是 JavaScript 操作网页的接口,全称为“文档对象模型”(Document Object Model)。它的作用是将网页转为一个 JavaScript 对象,从而可以用脚本进行各种操作(比如增删内容)。
浏览器会根据 DOM 模型,将结构化文档(比如 HTML 和 XML)解析成一系列的节点,再由这些节点组成一个树状结构(DOM Tree)。所有的节点和最终的树状结构,都有规范的对外接口。
节点类型
DOM 的最小组成单位叫做节点(node)。文档的树形结构(DOM 树),就是由各种不同类型的节点组成。每个节点可以看作是文档树的一片叶子。
节点的类型有七种。
Document
:整个文档树的顶层节点DocumentType
:doctype
标签(比如<!DOCTYPE html>
)Element
:网页的各种HTML标签(比如<body>
、<a>
等)Attribute
:网页元素的属性(比如class="right"
)Text
:标签之间或标签包含的文本Comment
:注释DocumentFragment
:文档的片段
浏览器提供一个原生的节点对象Node
,上面这七种节点都继承了Node
,因此具有一些共同的属性和方法。
如何确定节点类型
Node
有一个属性nodeType
表示Node
的类型,不同节点的nodeType
属性值和对应的常量如下
- 文档节点(document):9,对应常量
Node.DOCUMENT_NODE
- 元素节点(element):1,对应常量
Node.ELEMENT_NODE
- 属性节点(attr):2,对应常量
Node.ATTRIBUTE_NODE
- 文本节点(text):3,对应常量
Node.TEXT_NODE
- 文档片断节点(DocumentFragment):11,对应常量
Node.DOCUMENT_FRAGMENT_NODE
- 文档类型节点(DocumentType):10,对应常量
Node.DOCUMENT_TYPE_NODE
- 注释节点(Comment):8,对应常量
Node.COMMENT_NODE
确定节点类型时,使用nodeType
属性是常用方法。
var node = document.documentElement.firstChild;
if (node.nodeType === Node.ELEMENT_NODE) {
console.log('该节点是元素节点');
}
这些Node
类型中,我们最常用的就是 document
,element
,attribute
这几种类型。
参考: https://wangdoc.com/javascript/dom/node.html
创建元素
createElement
document.createElement`方法用来生成元素节点,并返回该节点。
var div = document.createElement('div')
使用createElement要注意:通过createElement创建的元素并不属于html文档,它只是创建出来,并未添加到html文档中,要调用appendChild或insertBefore等方法将其添加到HTML文档树中。
createTextNode
createTextNode用来创建一个文本节点,用法如下
var newDiv = document.createElement('div');
var newContent = document.createTextNode('Hello');
newDiv.appendChild(newContent);
// <div>Hello</div>
上面代码新建一个div
节点和一个文本节点,然后将文本节点插入div
节点。
这个方法可以确保返回的节点,被浏览器当作文本渲染,而不是当作 HTML 代码渲染。因此,可以用来展示用户的输入,避免 XSS 攻击。
var div = document.createElement('div');
div.appendChild(document.createTextNode('<span>Foo & bar</span>'));
console.log(div.innerHTML)
// <span>Foo & bar</span>
insertAdjacentElement
Element.insertAdjacentElement
方法在相对于当前元素的指定位置,插入一个新的节点。该方法返回被插入的节点,如果插入失败,返回null
。
element.insertAdjacentElement(position, element);
Element.insertAdjacentElement
方法一共可以接受两个参数,第一个参数是一个字符串,表示插入的位置,第二个参数是将要插入的节点。第一个参数只可以取如下的值。
beforebegin
:当前元素之前afterbegin
:当前元素内部的第一个子节点前面beforeend
:当前元素内部的最后一个子节点后面afterend
:当前元素之后
// HTML 代码:<body><div>some text</div></body>
var body = document.querySelector('body')
var p1 = document.createElement('p')
body.insertAdjacentElement('afterbegin', p1)
// 执行代码之后
// <body><p></p><div>some text</div></body>
insertAdjacentHTML, insertAdjacentText
Element.insertAdjacentHTML
方法用于将一个 HTML 字符串,解析生成 DOM 结构,插入相对于当前节点的指定位置。
element.insertAdjacentHTML(position, text);
该方法接受两个参数,第一个是一个表示指定位置的字符串,第二个是待解析的 HTML 字符串。position
参数的值与 insertAdjacentElement
的 position
取值相同
// HTML 代码:<div id="one">one</div>
var d1 = document.getElementById('one');
d1.insertAdjacentHTML('afterend', '<div id="two">two</div>');
// 执行后的 HTML 代码:
// <div id="one">one</div><div id="two">two</div>
该方法只是在现有的 DOM 结构里面插入节点,这使得它的执行速度比innerHTML
方法快得多。
注意,该方法不会转义 HTML 字符串,这导致它不能用来插入用户输入的内容,否则会有安全风险。
Element.insertAdjacentText
方法在相对于当前节点的指定位置,插入一个文本节点,用法与Element.insertAdjacentHTML
方法完全一致。
// HTML 代码:<div id="one">one</div>
var d1 = document.getElementById('one');
d1.insertAdjacentText('afterend', 'two');
// 执行后的 HTML 代码:
// <div id="one">one</div>two
修改元素
appendChild
appendChild()
方法接受一个节点对象作为参数,将其作为最后一个子节点,插入当前节点。该方法的返回值就是插入文档的子节点。
var p = document.createElement('p');
document.body.appendChild(p);
insertBefore
insertBefore
方法用于将某个节点插入父节点内部的指定位置。insertBefore
方法接受两个参数,第一个参数是所要插入的节点newNode
,第二个参数是父节点parentNode
内部的一个子节点referenceNode
。newNode
将插在referenceNode
这个子节点的前面。返回值是插入的新节点newNode
。
var p = document.createElement('p');
document.body.insertBefore(p, document.body.firstChild);
// 上面代码中,新建一个<p>节点,插在document.body.firstChild的前面,也就是成为document.body的第一个子节点。
removeChild
removeChild
方法接受一个子节点作为参数,用于从当前节点移除该子节点。返回值是移除的子节点。
var divA = document.getElementById('A');
divA.parentNode.removeChild(divA);
replaceChild
replaceChild
方法用于将一个新的节点,替换当前节点的某一个子节点。replaceChild
方法接受两个参数,第一个参数newChild
是用来替换的新节点,第二个参数oldChild
是将要替换走的子节点。返回值是替换走的那个节点oldChild
var divA = document.getElementById('divA');
var newSpan = document.createElement('span');
newSpan.textContent = 'Hello World!';
divA.parentNode.replaceChild(newSpan, divA);
// 将divA 替换成 newSpan
查询节点
获取单个节点
document.getElementById
根据元素id返回元素,返回值是Element类型,如果不存在该元素,则返回null。
使用这个接口有几点要注意:
(1)元素的Id是大小写敏感的,一定要写对元素的id
(2)HTML文档中可能存在多个id相同的元素,则返回第一个元素
(3)只从文档中进行搜索元素,如果创建了一个元素并指定id,但并没有添加到文档中,则这个元素是不会被查找到的// HTML代码为
// <span id="myspan">Hello</span>
var span = document.getElementById('myspan');
span.id // "myspan"
span.tagName // "SPAN"
document.querySelector
Element.querySelector
方法接受 CSS 选择器作为参数,返回父元素的第一个匹配的子元素。如果没有找到匹配的子元素,就返回null
。// 查找元素使用 document.querySelector() 函数
// 这个函数的参数是一个选择器(和 CSS 选择器一样)
// 选择器语法和 CSS 选择器一样, 现在只用 3 个基础选择器
// 元素选择器
var body = document.querySelector('body')
// class 选择器, 用的是 .类名
var form = document.querySelector('.login-form')
// id 选择器, 用的是 #id
var loginButton = document.querySelector('#id-button-login')
// log 出来看看 // 选择多个元素使用函数 querySelectorAll
var buttons = document.querySelectorAll('.radio-button')
// 还可以接受任何复杂的 CSS 选择器
document.body.querySelector("style[type='text/css'], style:not([type])"); // 查找到的元素还可以继续用 querySelector
var ul = document.querySelector('.ul')
ul.querySelector('li')
获取多个节点
document.getElementsByTagName
document.getElementsByClassName
document.getElementsByName
document.querySelectorAll
获取父节点
parentElement 和 parentNode
获取所有的后代节点
children
属性返回一个HTMLCollection
实例,成员是当前节点的所有元素子节点。
childNodes
属性返回一个类似数组的对象(NodeList
集合),成员包括当前节点的所有子节点,注意,除了元素节点,childNodes
属性的返回值还包括文本节点和注释节点。
children 和 childNodes 最大的区别就是:children 不会把空白节点算进去。
获取兄弟节点
- previousSibling,nextSibling,previousElementSibling,nextElementSibling
- 空白节点的坑,previousSibling,nextSibling会把空白节点算进去
操作 CSS
style
// 在单个语句中设置多个样式
elt.style.cssText = "color: blue; border: 1px solid black";
// 或者
elt.setAttribute("style", "color:red; border: 1px solid blue;");
// 设置特定样式,同时保持其他内联样式值不变
elt.style.color = "blue";
classList
var element = document.querySelector('.active')
if (element != null) {
// 使用 classList 可以访问一个元素的所有 class
// remove 可以删除一个 class
element.classList.remove("active")
}
element.classList.add('active') // 添加 active样式
element.classList.contains('active') //判断是否包含 active 样式
element.classList.toogle('active') // 如果存在 active 样式就删除,否则就添加
获取元素的位置
获取 DOM 元素相对于文档的位置,可以直接使用 offsetTop
获取 DOM 元素相对于视口的位置,可以使用 getBoundingClientRect()
获取 SVG 元素或行内元素的 CSS 盒子(比如用来做文本高亮时),可以使用 getClientRects();
获取绝对定位元素、伪元素的渲染后 CSS 属性,可以使用 getComputedStyle()
获取网页的总宽高
document.body.clientWidth
document.body.clientHeight
获取视口(浏览器可见区域)的宽高
document.documentElement.clientWidth
document.documentElement.clientHeight
JavaScript 操作 DOM 总结的更多相关文章
- JavaScript 操作 DOM 常用 API 总结
文本整理了javascript操作DOM的一些常用的api,根据其作用整理成为创建,修改,查询等多种类型的api,主要用于复习基础知识,加深对原生js的认识. 基本概念 在讲解操作DOM的api之前, ...
- 使用原生 JavaScript 操作 DOM
原文:https://www.sitepoint.com/dom-manipulation-vanilla-javascript-no-jquery/ 微软官方放弃了 IE10-,所以现在可以放心使用 ...
- Python javascript操作DOM
文档对象模型(Document Object Model,DOM)是一种用于HTML和XML文档的编程接口.它给文档提供了一种结构化的表示方法,可以改变文档的内容和呈现方式.我们最为关心的是,DOM把 ...
- javaScript操作DOM对象(看三遍,敲三遍,写三遍! 不会你找我)!!
DOM是Document Object Model的缩写,即文档对象模型,是基于文档编程的一套API 使用javaScript操作DOM对象通常分为三类:1.DOM CORE 2.HTM ...
- 第四章 JavaScript操作DOM对象
第四章 JavaScript操作DOM对象 一.DOM操作 DOM是Document Object Model的缩写,即文档对象模型,是基于文档编程的一套API接口,1988年,W3C发布了第一级 ...
- 你所不了解的javascript操作DOM的细节知识点(一)
你所不了解的javascript操作DOM的细节知识点(一) 一:Node类型 DOM1级定义了一个Node接口,该接口是由DOM中的所有节点类型实现.每个节点都有一个nodeType属性,用于表明节 ...
- JavaScript 操作DOM对象
1)JavaScript 操作DOM對象 1.DOM:是Document Object Model 的缩写,及文档对象模型 2.DOM通常分为三类:DOM Core(核心).HTML-DOM 和 ...
- 【repost】Javascript操作DOM常用API总结
Javascript操作DOM常用API总结 文本整理了javascript操作DOM的一些常用的api,根据其作用整理成为创建,修改,查询等多种类型的api,主要用于复习基础知识,加深对原生js的认 ...
- JQuery制作网页—— 第三章 JavaScript操作DOM对象
1. DOM:Document Object Model(文档对象模型): DOM操作: ●DOM是Document Object Model的缩 ...
- 使用jQuery快速高效制作网页交互特效-----JavaScript操作DOM对象
一.DOM操作分类 使用JavaScript操作DOM时通常分为三类:DOM Core.HTMl--DOM和CSS-DOM 二.访问节点 节点属性 三.节点信息 四.操作节点的属性 语法: ge ...
随机推荐
- 在.net core的web项目中使用kindeditor
本项目是一个.net core的mvc项目 1.下载kindeditor 4.1.11 解压后将文件夹置于 wwwroot目录下,如图: 2.在HomeController的Index控制器对应的in ...
- 距离北京奥运还有359天,发布WPF版本的北京2008标志(下)
原文:距离北京奥运还有359天,发布WPF版本的北京2008标志(下) 图片显示效果: XAML代码: <Viewbox Width="463.548828" Height ...
- 回调函数实现类似QT中信号机制
1. 定义回调接口类: class UIcallBack { public: virtual void onAppActivated() = 0; virtual void onShowMore() ...
- Linux性能测试 pmap命令
名称: pmap - report memory map of a process(查看进程的内存映像信息)用法 pmap [ -x | -d ] [ -q ] pids... ...
- HDU 4919 打表找规律 java睑板 map 递归
== oeis: 点击打开链接 瞎了,x.mod(BigInteger.ValueOf(2)).equal( BigInteger.ValueOf(1)) 写成了 x.mod(BigInteger.V ...
- Python 函数调用性能记录
之前用 JS 写项目的时候,项目组用的组件模式,一直感觉很不错.最近用 Python 做新项目,项目结构也延续了组件模式.一直没有对函数调用的性能作了解,今天突发奇想测试了一下,写了一些测试代码 首先 ...
- Matlab随笔之画图函数总结
原文:Matlab随笔之画图函数总结 MATLAB函数画图 MATLAB不但擅长於矩阵相关的数值运算,也适合用在各种科学目视表示(Scientific visualization).本节将介绍MATL ...
- CountDownLatch和CyclicBarrier 专题
4.Runnable接口和Callable接口的区别 有点深的问题了,也看出一个Java程序员学习知识的广度. Runnable接口中的run()方法的返回值是void,它做的事情只是纯粹地去执行ru ...
- C++成员函数指针错误用法警示(成员函数指针与高性能的C++委托,三篇),附好多评论
今天做一个成绩管理系统的并发引擎,用Qt做的,仿照QtConcurrent搞了个模板基类.这里为了隐藏细节,隔离变化,把并发的东西全部包含在模板基类中.子类只需注册需要并发执行的入口函数即可在单独线程 ...
- OC笔记一:Objective
1.OC简介 全称:Objective-C,是扩充C的面向对象编程语言,主要用于iOS和Mac OS开发. C语言的基础上,增加了一层最小的面向对象语法 完全兼容C语言 可以在OC代码中混入C语言代码 ...