JavaScript入门⑦-DOM操作大全
<p><img src="https://img2022.cnblogs.com/blog/151257/202211/151257-20221114201138535-717334047.png" alt="image.png" loading="lazy"></p><p><strong>JavaScript入门系列目录</strong></p>
<ul>
<li>JavaScript入门①-基础知识筑基</li>
<li>JavaScript入门②-函数(1)基础{浅出}</li>
<li>JavaScript入门③-函数(2)原理{深入}执行上下文</li>
<li>JavaScript入门④-万物皆对象:Object</li>
<li>JavaScript入门⑤-欲罢不能的对象、原型与继承</li>
<li>JavaScript入门⑥-WEB浏览器API</li>
<li>JavaScript入门⑦-DOM操作大全</li>
<li>JavaScript入门⑧-事件总结大全</li>
<li>JavaScript入门⑨-异步编程●异世界之旅</li>
<li>JavaScript入门⑩-ES6归纳总结</li>
</ul>
<h1 id="01domdocument">01、DOM(document)</h1>
<p><strong>DOM</strong>(Document Object Model)<strong>文档对象模型</strong>,将文档<code>document</code>解析为一个由节点和对象(包含属性和方法的对象)组成的逻辑树,每个节点都是一个对象,<strong><code>document</code></strong> 对象就是整个DOM树的根节点。DOM提供的API方法用来管理这棵树,用JavaScript 等脚本语言操作文档结构、样式和内容。</p>
<p><img src="https://img2022.cnblogs.com/blog/151257/202211/151257-20221114201138531-845025008.jpg" alt="5f9f1289909ffdf88033e5bd92ad7ae9_v2-30a65f5bc123bc513dc2584c5c2e517f_1440w_source=172ae18b.jpg" loading="lazy"></p>
<h2 id="11dom结构-节点元素">1.1、DOM结构-节点/元素</h2>
<p>DOM树是由很多节点构成,分为下面几种类型,注意节点是包含文本、注释的。</p>
<table>
<thead>
<tr>
<th><strong>节点类型</strong></th>
<th><strong>描述</strong></th>
<th><strong>示例</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td><code>document</code>文档节点</td>
<td><code>document</code>文档本身,DOM的入口(根)</td>
<td>document</td>
</tr>
<tr>
<td><code>element</code>元素节点</td>
<td>所有HTML元素<code>Element</code> /ˈelɪmənt/ i</td>
<td>html、body、a、p</td>
</tr>
<tr>
<td><code>attribute</code>属性节点</td>
<td>元素的属性</td>
<td>id、name、href、class</td>
</tr>
<tr>
<td>文本节点</td>
<td>元素内的文本形成文本节点</td>
<td>文本字符、换行、空格</td>
</tr>
<tr>
<td>注释节点</td>
<td>注释</td>
<td><code><!--注释--></code></td>
</tr>
</tbody>
</table>
<p>一颗完整的DOM树,除了显而易见的元素,还有注释、换行符构成的文本类节点。</p>
<pre><code class="language-html"><!DOCTYPE HTML>
<html>
<body>
The truth about elk.
<ol>
<li>An elk is a smart</li>
<!-- comment -->
<li>...and cunning animal!</li>
</ol>
</body>
</html>
</code></pre>
<p><img src="https://img2022.cnblogs.com/blog/151257/202211/151257-20221114201138585-2082486970.png" alt="image.png" loading="lazy"></p>
<blockquote>
<p>当前选择元素<code>$0</code>:在浏览器控制台中,<code>$0</code>标识当前选中的元素。<code>$0.style.background='red';</code></p>
</blockquote>
<p>节点和元素在DOM树上的不同视图(导航方式)如下图,现代JS中主要使用元素导航属性。</p>
<p><img src="https://img2022.cnblogs.com/blog/151257/202211/151257-20221114201138510-59277965.png" alt="image.png" loading="lazy"><img src="https://img2022.cnblogs.com/blog/151257/202211/151257-20221114201138453-1270435833.png" alt="image.png" loading="lazy"></p>
<table>
<thead>
<tr>
<th><strong>✅节点-导航属性</strong></th>
<th><strong>描述</strong></th>
<th><strong>✅元素-导航属性</strong></th>
<th><strong>描述</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td><code>parentNode</code></td>
<td>父节点</td>
<td><code>parentElement</code></td>
<td>父元素,一般和<code>parentNode一样</code>,只有document.documentElement不同</td>
</tr>
<tr>
<td><code>firstChild</code></td>
<td>第一个子节点</td>
<td><code>firstElementChild</code></td>
<td>第一个子元素</td>
</tr>
<tr>
<td><code>lastChild </code></td>
<td>最后一个子节点</td>
<td><code>lastElementChild</code></td>
<td>最后一个子元素</td>
</tr>
<tr>
<td><code>childNodes</code></td>
<td>子节点集合</td>
<td><code>children</code></td>
<td>子元素集合</td>
</tr>
<tr>
<td><code>nextSibling </code></td>
<td>下一个兄弟节点</td>
<td><code>nextElementSibling</code></td>
<td>下一个兄弟元素( Sibling/ˈsɪblɪŋ/ 兄弟)</td>
</tr>
<tr>
<td><code>previousSibling </code></td>
<td>上一个兄弟节点</td>
<td><code>previousElementSibling</code></td>
<td>上一个兄弟元素(/ˈpriːviəs/以前 )</td>
</tr>
</tbody>
</table>
<pre><code class="language-javascript">document.documentElement.parentNode; //HTMLDocument
document.documentElement.parentElement; //null
document.body.childNodes.length; //33
document.body.children.length; //16
document.body.firstElementChild;
</code></pre>
<blockquote>
<p><strong>❓元素节点</strong>:这里的导航属性都是<strong>只读</strong>的,不可用于插入、修改元素;都是<strong>实时</strong>的;<strong>集合</strong>是可迭代的,用<code>for..of</code>,不要用<code>for(in)</code></p>
</blockquote>
<h2 id="12节点node元素element">1.2、节点Node/元素Element</h2>
<p>节点/元素的继承层次结构如下,最基础的<code>EventTarget </code>又继承自<code>Object</code>,因此可以自由添加属性、方法。</p>
<p><img src="https://img2022.cnblogs.com/blog/151257/202211/151257-20221114201138480-993310217.png" alt="image.png" loading="lazy"></p>
<ul>
<li><strong>EventTarget</strong>:—— 是一切的根(“抽象(abstract)”类),定义了基础的事件。</li>
<li><strong>Node</strong>:也是一个“抽象”类,充当 DOM 节点的基础,提供了节点导航功能,如parentNode,nextSibling,childNodes 等。</li>
<li><strong>Document</strong>:表示整个文档,全局变量<code>document</code>就是他。</li>
<li><strong>CharacterData</strong>:一个文本“抽象”类,被Text(文本节点) 、Comment (注释节点)继承。(Character/ˈkærəktər/ 符号文字)</li>
<li><strong>Element</strong>:是 DOM 元素的基础类,提供了元素导航功能,如nextElementSibling,children等,以及搜索方法<code>getElementsByTagName</code> 和 <code>querySelector</code>等。</li>
<li><strong>HTMLElement</strong>:所有 HTML 元素的基础类,常用的如:HTMLInputElement、HTMLBodyElement、HTMLAnchorElement、HTMLDivElement、HTMLTableElement</li>
</ul>
<pre><code class="language-javascript">document.body.querySelector("div").constructor.name; //HTMLDivElement
document.body.querySelector("div").toString(); //
</code></pre>
<h3 id="node节点">🔸Node节点</h3>
<p>Node节点对象的属性:</p>
<table>
<thead>
<tr>
<th><strong>Node</strong><strong>属性/方法</strong></th>
<th><strong>描述</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>data</td>
<td>文本/注释节点的文本值,可修改,注释节点可用来存放一些待处理内容</td>
</tr>
<tr>
<td>nodeName</td>
<td>节点名称</td>
</tr>
<tr>
<td>textContent</td>
<td><strong>元素</strong>内文本,不含标签。可修改,可安全的写入文本。</td>
</tr>
<tr>
<td><strong>appendChild</strong>(node)</td>
<td>从末尾追加一个子节点</td>
</tr>
<tr>
<td><strong>removeChild</strong>(child)</td>
<td>删除一个子节点</td>
</tr>
<tr>
<td><strong>replaceChild</strong>(new,old)</td>
<td>替换一个子节点</td>
</tr>
<tr>
<td><strong>insertBefore</strong>(new,ref)</td>
<td>在ref节点前插入一个节点</td>
</tr>
<tr>
<td><strong>cloneNode</strong>(deep)</td>
<td>克隆当前节点副本,deep=true会克隆其所有后代,否则只是节点本身</td>
</tr>
<tr>
<td><strong>contains</strong>( node)</td>
<td>是否包含指定的后代节点,返回bool</td>
</tr>
<tr>
<td><strong>hasChildNodes</strong>()</td>
<td>是否包含子节点,返回bool</td>
</tr>
</tbody>
</table>
<pre><code class="language-javascript">// <div id="div">div内容<p>p内容</p></div>
let div = document.querySelector('#div');
console.log(div.innerHTML,div.textContent,div.innerText); //div内容<p>p内容</p>div内容p内容div内容\n\np内容
console.log(div.nodeName, div.localName, div.tagName); //DIV divDIV
</code></pre>
<h3 id="element-元素">🔸Element 元素</h3>
<p><strong>Element</strong> 基类元素对象提供的属性方法:</p>
<table>
<thead>
<tr>
<th><strong>✅</strong><strong>Element</strong><strong>属性</strong></th>
<th><strong>描述</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>id</td>
<td>唯一<code>id</code>,基础通用属性还要<code>name</code>、<code>class</code>、<code>style</code></td>
</tr>
<tr>
<td>localName</td>
<td>本地化名称,名称相关的还有<code>nodeName</code>、<code>tagName</code></td>
</tr>
<tr>
<td><strong>classList</strong>、<strong>className</strong></td>
<td>class样式集合、class样式值,集合可以新增、删除。</td>
</tr>
<tr>
<td><strong>innerHTML</strong></td>
<td>元素标签内的所有HTML内容,可以修改,<strong>注意</strong><code>innerHTML+=</code>会进行完全重写</td>
</tr>
<tr>
<td><strong>outerHTML</strong></td>
<td>包含元素本身及其内部的所有HTML内容,可以修改(删除并替换)</td>
</tr>
<tr>
<td>innerText</td>
<td>元素标签内的所有文本节点值,包含所有后代节点的文本。</td>
</tr>
<tr>
<td>hidden</td>
<td>是否隐藏的bool属性,</td>
</tr>
<tr>
<td><strong>✅方法</strong></td>
<td><br></td>
</tr>
<tr>
<td><strong>addEventListener</strong>()</td>
<td>注册实践到EventTarget,还有配套的<code>removeEventListener()</code></td>
</tr>
<tr>
<td><strong>append</strong>(node...)</td>
<td>在末尾追加多个子节点(或DOMString=text节点)</td>
</tr>
<tr>
<td><strong>prepend</strong>(node...)</td>
<td>在开头插入多个子节点(或DOMString)</td>
</tr>
<tr>
<td><strong>after</strong>(node...)</td>
<td>在后面插入节点(或DOMString)</td>
</tr>
<tr>
<td><strong>before</strong>(node...)</td>
<td>在前面插入节点(或DOMString)</td>
</tr>
<tr>
<td><strong>replaceWith</strong>(node)</td>
<td>将 node 替换为给定的节点或字符串</td>
</tr>
<tr>
<td><strong>remove</strong>(element)</td>
<td>把对象从它所属的 DOM 树中删除</td>
</tr>
<tr>
<td>scroll()/scrollBy()</td>
<td>元素内滚动</td>
</tr>
<tr>
<td><strong>✅事件</strong>(event)</td>
<td><br></td>
</tr>
<tr>
<td><strong>blur</strong>(event)、focusout()</td>
<td>元素失去焦点,<strong>blur</strong>不会冒泡 (blue /blɜːr/ 模糊)</td>
</tr>
<tr>
<td><strong>focus</strong>、focusin</td>
<td>元素获取焦点时触发,<strong>focus</strong>不会冒泡</td>
</tr>
<tr>
<td><strong>keydown</strong><strong>、keyup</strong></td>
<td>键盘按键按下、松开时触发</td>
</tr>
<tr>
<td><strong>click</strong>(event)</td>
<td>点击触发,通常是鼠标左键在一个元素上被按下并放开时</td>
</tr>
<tr>
<td>dblclick</td>
<td>双击触发事件</td>
</tr>
<tr>
<td>mousedown、mouseup</td>
<td>鼠标按下、弹起时触发</td>
</tr>
<tr>
<td>mousemove</td>
<td>鼠标在元素上移动时触发</td>
</tr>
<tr>
<td>onmouseover、mouseout</td>
<td>鼠标移入、移出元素区域时触发</td>
</tr>
<tr>
<td>mouseenter、mouseleave</td>
<td>鼠标移入、移出元素区域时触发,与上面不同的是不会冒泡</td>
</tr>
</tbody>
</table>
<pre><code class="language-html"><div class="h1 c2" id="firstDiv" myatt="自定义特性" order="asc">Element</div>
<script>
let div = document.querySelector('#firstDiv');
div.classList.add("c5");
div.setAttribute("att2", 3) //添加、设置属性值
div.addEventListener("click",
(event) => {
console.log(event)
});
div.hidden = true;
</script>
</code></pre>
<blockquote>
<p><strong>📢注意</strong>:DOM操作必须等节点初始化完成后才能进行。可以在html尾部执行JS,或者在<code>window</code>的<code>onload</code>事件中处理</p>
</blockquote>
<h2 id="13元素特性attribute">1.3、元素特性Attribute</h2>
<p>元素特性的操作方法:</p>
<table>
<thead>
<tr>
<th><strong>Element-特性方法</strong></th>
<th><br></th>
</tr>
</thead>
<tbody>
<tr>
<td>attributes</td>
<td>所有属性节点的一个实时集合,支持移除项、属性值操作,<code>ele.attributes["href"].value</code></td>
</tr>
<tr>
<td><strong>getAttribute</strong>(attName)</td>
<td>获取属性值</td>
</tr>
<tr>
<td><strong>getAttributeNames</strong>()</td>
<td>所有属性名数组</td>
</tr>
<tr>
<td><strong>setAttribute</strong>(attName,value)</td>
<td>设置属性值,可以新增自定义特性,常用于设置css</td>
</tr>
<tr>
<td><strong>removeAttribute</strong>(attName)</td>
<td>从指定的元素中删除一个属性</td>
</tr>
<tr>
<td><strong>hasAttribute</strong>(attName)</td>
<td>判断是否包含指定属性,返回一个布尔值</td>
</tr>
<tr>
<td>hasAttributes()</td>
<td>判断是否包含属性,返回一个布尔值</td>
</tr>
</tbody>
</table>
<ul>
<li><strong>特性</strong>(attribute)—— 写在 HTML 中的内容,值都是字符串,大小写<strong>不明感</strong>。</li>
<li><strong>属性</strong>(property)—— DOM 对象中的内容,大小写敏感。</li>
</ul>
<blockquote>
<p><strong>❗特性attribute</strong>与<strong>属性property</strong>:元素上的特性<code>attribute</code>与属性<code>property</code>基本上都是一致相对应的。也有个别例外,如<code>input.value</code>只能单向从特性<code>attribute</code>同步到属性<code>property</code>。</p>
</blockquote>
<pre><code class="language-html"><style>
span {
color: green;
}
span {
color: red;
}
</style>
<div>
<span data-status="success">操作结果</span> <!--自定义特性用来设置元素状态样式-->
</div>
<script>
const espan = document.querySelector("span");
console.log(espan.attributes); //所有属性集合
console.log(espan.getAttributeNames()); //['data-status', 'class', 'style']
console.log(espan.hasAttribute("data-status")); //true
//切换样式
espan.attributes["data-status"].value="failure";
espan.dataset.status="failure";
espan.setAttribute("data-status","failure");
espan.class="success";
</script>
</code></pre>
<p><strong>dataset</strong>属性用来存放自定义的非标准特性,自定义的特性都以“data-”开头,这是专门保留给程序猿门使用的。如“data-status”,通过<code>elem.dataset.status</code>访问(属性上没有前缀<code>date-</code>)。这样可以避免HML语言升级后造成的名称冲突。</p>
<h2 id="14元素的大小位置">1.4、元素的大小位置</h2>
<table>
<thead>
<tr>
<th><strong>Element-大小位置</strong></th>
<th><strong>描述</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>clientHeight、clientWidth</td>
<td>元素内部高度、宽度,包括内边距(不含边框)</td>
</tr>
<tr>
<td>offsetWidth/offsetHeight</td>
<td>元素完整的宽度、高度,为元素的完整大小,包括border</td>
</tr>
<tr>
<td>clientTop/Left</td>
<td>元素边框宽度,同border宽度</td>
</tr>
<tr>
<td>offsetLeft/Top</td>
<td>元素相对于 offsetParent 左上角的 x/y 坐标</td>
</tr>
<tr>
<td>scrollHeight 、scrollWidth</td>
<td>元素滚动视图的高度、宽度,包含滑动隐藏部分。</td>
</tr>
<tr>
<td>scrollLeft/scrollTop</td>
<td>元素滚出去(隐藏)的部分宽度、高</td>
</tr>
</tbody>
</table>
<p><img src="https://img2022.cnblogs.com/blog/151257/202211/151257-20221114201138471-725878435.png" alt="image.png" loading="lazy"></p>
<pre><code class="language-html"><style>
#sdiv {
border: 5px solid pink;
padding: 5px;
margin: 5px;
width: 200px;
height: 50px;
overflow: auto;
}
</style>
<div id="sdiv">
光圈效应:会导致爱屋及乌的认知偏差,名人效应就是典型的光环效应。与之相反的是音叉效应(恶魔效应)。
</div>
<script>
let sdiv = document.querySelector('#sdiv');
console.log(sdiv.clientWidth, sdiv.clientHeight); //193 60
console.log(sdiv.offsetWidth, sdiv.offsetHeight); //214 70
console.log(sdiv.scrollWidth, sdiv.scrollHeight); //193 115
console.log(sdiv.clientLeft,sdiv.clientHeight); //5 60
console.log(sdiv.offsetLeft,sdiv.offsetTop); //13 261
console.log(sdiv.scrollLeft,sdiv.scrollTop); //0 0
</script>
</code></pre>
<p><img src="https://img2022.cnblogs.com/blog/151257/202211/151257-20221114201138496-559382672.png" alt="image.png" loading="lazy"></p>
<h2 id="15document">1.5、document</h2>
<table>
<thead>
<tr>
<th><strong>✅</strong><strong>document</strong><strong>属性</strong></th>
<th><strong>描述</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>documentElement</td>
<td>对应 <code><html></code> 标签的 顶层节点</td>
</tr>
<tr>
<td>all、head、<strong>body</strong></td>
<td>所有元素的集合、head节点、body节点</td>
</tr>
<tr>
<td>images</td>
<td>所有<code><image></code>图片元素集合</td>
</tr>
<tr>
<td>forms</td>
<td>所有表单元素 <code><form></code> 的列表</td>
</tr>
<tr>
<td>links</td>
<td>所有超链接的列表</td>
</tr>
<tr>
<td>scripts</td>
<td>所有的 <code><script></code> 元素</td>
</tr>
<tr>
<td><strong>✅扩展属性</strong></td>
<td>继承自 HTMLDocument 接口</td>
</tr>
<tr>
<td>title</td>
<td>文档标题(浏览器页签显示的名称)来自<code><title></code>标签,可以动态修改。</td>
</tr>
<tr>
<td><strong>readyState</strong></td>
<td>document 的加载状态:loading( 文档正在被加载)、interactive( 文档被全部读取,/ˌɪntərˈæktɪv/ 交互)、complete(包括资源都已加载完成)</td>
</tr>
<tr>
<td>domain、URL</td>
<td>网址域名、完整URL地址。还有个<code>location</code>属性同<code>window.location</code></td>
</tr>
<tr>
<td>cookie</td>
<td>前页面的Cookie</td>
</tr>
<tr>
<td>defaultView</td>
<td>当前window的引用,<code>window===document.defaultView; //true</code></td>
</tr>
</tbody>
</table>
<pre><code class="language-javascript">console.log(document.documentElement.childNodes); //
console.log(document.documentElement.children); //
//京东首页
console.log(document.all.length, document.images.length, ); //8438 433
console.log(document.links.length, document.scripts.length); //2771 34
console.log(document.title); //京东(JD.COM)-正品低价、品质保障、配送及时、轻松购物!
console.log(document.readyState); //complete
console.log(document.domain, document.URL); //www.jd.comhttps://www.jd.com/
console.log(document.cookie);
console.log(document.defaultView === window); //true
</code></pre>
<hr>
<h1 id="02查找dom元素">02、查找DOM元素</h1>
<p>查找元素、节点的相关方法,最常用、好用的就是<code>querySelector(cssSelector)</code>了,参数就是css选择器,这个方法设计的不错👍。</p>
<table>
<thead>
<tr>
<th><strong>属性/方法</strong></th>
<th><strong>描述</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>querySelector</strong>(css)</td>
<td>根据选择器查询返回<strong>第一个元素</strong>,selectors同CSS选择器</td>
</tr>
<tr>
<td><strong>querySelectorAll</strong>(css)</td>
<td>根据选择器查询返回<strong>NodeList</strong>集合(静态集合)</td>
</tr>
<tr>
<td><strong><code>id</code></strong>全局变量</td>
<td>元素<code>id</code>作为全局变量访问:<code>hid.innerText="33";``window['hid']</code><br>不推荐使用:容易命名冲突,不容易分辨变量来源</td>
</tr>
<tr>
<td>elem.<strong>matches</strong>(css)</td>
<td>判断是否匹配css选择器,返回<code>true</code>、<code>false</code></td>
</tr>
<tr>
<td>elem.<strong>closest</strong>(css)</td>
<td>查找离元素<strong>最近的</strong>+<strong>css匹配的</strong>+<strong>祖先</strong>(/klosɪst/靠近),包含elem自己</td>
</tr>
<tr>
<td>document.<strong>getElementById</strong>(id)</td>
<td>根据id获取<strong>一个元素</strong>,id重复则取第一个</td>
</tr>
<tr>
<td>document.<strong>getElementsByName</strong>(name)</td>
<td>根据<code>name</code>属性获取元素<strong>集合</strong>(动态),多用于单选框、复选框</td>
</tr>
<tr>
<td><strong>getElementsByClassName</strong>(class)</td>
<td>根据<code>class</code>属性值获取元素<strong>集合</strong>(动态,会实时更新)</td>
</tr>
<tr>
<td><strong>getElementsByTagName</strong>(tag)</td>
<td>根据元素标签名元素<strong>集合</strong>(动态),<code>getElementsByTagName("div")</code></td>
</tr>
</tbody>
</table>
<pre><code class="language-javascript">//id=sdiv,可以直接使用
console.log(sdiv.matches('.cname')) //false
console.log(sdiv.closest(':not(div)')); //body
document.body.getElementsByTagName("div"); //HTMLCollection
document.body.querySelectorAll("div"); //NodeList
document.body.querySelector("div") === document.body.querySelectorAll("div"); //true
console.log(sdiv.closest(':not(div)')); //body
</code></pre>
<hr>
<h1 id="03增删改dom元素">03、增删改DOM元素</h1>
<table>
<thead>
<tr>
<th><strong>属性/方法</strong></th>
<th><strong>描述</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>createElement</strong>(tagName)</td>
<td>根据标签名创建节点元素:<code>document.createElement("div")</code></td>
</tr>
<tr>
<td><strong>createTextNode</strong>(text)</td>
<td>创建一个文本节点。也可用<code>innerText</code>直接设置文本内容。</td>
</tr>
<tr>
<td>ele.<strong>append</strong>(child...)</td>
<td>在末尾追加多个子节点(或DOMString=text节点)</td>
</tr>
<tr>
<td>ele.<strong>prepend</strong>(child...)</td>
<td>在开头插入多个子节点(或DOMString)</td>
</tr>
<tr>
<td>ele.<strong>after</strong>(node...)</td>
<td>在后面插入节点(或DOMString)</td>
</tr>
<tr>
<td>ele.<strong>before</strong>(node...)</td>
<td>在前面插入节点(或DOMString)</td>
</tr>
<tr>
<td>ele.<strong>replaceWith</strong>(node, ... nodes)</td>
<td>将 <code>ele</code>替换为给定的节点或字符串</td>
</tr>
<tr>
<td>ele.<strong>remove</strong>(element)</td>
<td>把对象从它所属的 DOM 树中删除</td>
</tr>
<tr>
<td>elem.<strong>insertAdjacentHTML</strong>(where, html)</td>
<td>插入html字符,不会影响现有元素,性能比innerHTML 更好!</td>
</tr>
<tr>
<td>node.<strong>cloneNode</strong>(deep)</td>
<td>克隆当前节点副本,deep=true会克隆其所有后代,否则只是节点本身</td>
</tr>
<tr>
<td>ele.innerHTML</td>
<td>设置标签HTML内容,也可以达到创建节点内容的目的</td>
</tr>
<tr>
<td>ele.<strong>innerText</strong></td>
<td>设置标签文本内容,兼容性最好?</td>
</tr>
<tr>
<td>node.textContent</td>
<td>设置节点文本内容,效果同上</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>📢注意</strong>:</p>
<ul>
<li><strong>移动插入</strong>:所有插入方法,如果插入的是已存在DOM树上节点,都会自动从旧的位置删除再插入到新的位置。</li>
<li><strong>下拉框</strong><code>select</code>的选项<code>option</code>可以通过其属性<code>options</code>添加。<code>obj1.options.add(new Option("abc",3))</code></li>
</ul>
</blockquote>
<pre><code class="language-javascript">let parent = document.createElement("div"); //这两个命名(parent、child)和window有冲突的,虽然可以用
let child = document.createElement("p");
child.innerText = "p-innertext";
parent.appendChild(child);
parent.append("sam1", "sam2"); //插入多个文本节点
child.replaceWith(document.createElement("span"), "text-");//替换节点
console.log(parent.outerHTML); //<div><span></span>text-sam1sam2</div>
parent.innerHTML = "<p>ptext</p>";
console.log(parent.outerHTML); //<div><p>ptext</p></div>
parent.innerText = "<p>ptext</p>"; //会被转义
console.log(parent.outerHTML); //<div>&lt;p&gt;ptext&lt;/p&gt;</div>
sdiv.append(parent);
</code></pre>
<h2 id="31远古的node方法">3.1、远古的node方法</h2>
<p>远古时期流传下来的<code>node</code>提供的插入节点的方法,返回参数都是<code>Node</code>。和<code>element</code>方法主要区别是<code>element</code>的方法参数可多个,方法也更简洁。</p>
<table>
<thead>
<tr>
<th><strong>属性/方法</strong></th>
<th><strong>描述</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>node.<strong>appendChild</strong>(child)</td>
<td>从末尾追加一个子节点,支持字符串参数</td>
</tr>
<tr>
<td>node.<strong>insertBefore</strong>(new,ref)</td>
<td>在ref节点前插入一个节点</td>
</tr>
<tr>
<td>node.<strong>replaceChild</strong>(new,old)</td>
<td>替换一个子节点</td>
</tr>
<tr>
<td>node.<strong>removeChild</strong>(child)</td>
<td>删除一个子节点</td>
</tr>
</tbody>
</table>
<h2 id="32insertadjacenthtmltextelement">3.2、insertAdjacentHTML/Text/Element</h2>
<p>插入HTML字符、文本、元素节点的通用方法:(adjacent /əˈdʒeɪs(ə)nt/ 相邻的)。</p>
<table>
<thead>
<tr>
<th><strong>属性/方法</strong></th>
<th><strong>描述</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>elem.<strong>insertAdjacentHTML</strong>(where, html)</td>
<td>插入html字符,不会影响现有元素</td>
</tr>
<tr>
<td>elem.<strong>insertAdjacentElement</strong>(where, element)</td>
<td>插入元素</td>
</tr>
<tr>
<td>elem.<strong>insertAdjacentText</strong>(where, text)</td>
<td>插入文本</td>
</tr>
</tbody>
</table>
<p>参数where是一个枚举字符,这个谁取的名真头疼:</p>
<ul>
<li>'<strong>beforebegin</strong>':元素自身的前面。</li>
<li>'<strong>afterbegin</strong>':插入元素内部的第一个子节点之前。</li>
<li>'<strong>beforeend</strong>':插入元素内部的最后一个子节点之后。</li>
<li>'<strong>afterend</strong>':元素自身的后面。</li>
</ul>
<p><img src="https://img2022.cnblogs.com/blog/151257/202211/151257-20221114203251810-2016823099.png" alt="image" loading="lazy"></p>
<pre><code class="language-html"><div>
<span id="adjacent">div</span>
</div>
<script>
const adiv = document.getElementById("adjacent");
adiv.insertAdjacentHTML("beforebegin", "-beforebegin-");
adiv.insertAdjacentText("afterbegin","-afterbegin-")
adiv.insertAdjacentText("beforeend","-beforeend-")
adiv.insertAdjacentText("afterend","-afterend-")
console.log(adiv.parentElement.innerHTML);
//-beforebegin-<span id="adjacent">-afterbegin-div-beforeend-</span>-afterend-
</script>
</code></pre>
<h2 id="33documentfragment包装器">3.3、DocumentFragment包装器</h2>
<p>DocumentFragment 是一个特殊的节点,像一个容器,用来附加其他节点,然后传输给其他方法使用,当然好像也可以用数组代替。(Fragment/ˈfræɡmənt/ 片段)</p>
<pre><code class="language-javascript">const adiv=document.getElementById("adjacent");
let fram=new DocumentFragment();
fram.append(document.createElement("li"));
fram.append(document.createElement("li"));
adiv.append(fram);
console.log(adiv.outerHTML);
</code></pre>
<hr>
<h1 id="04dom样式管理">04、DOM样式管理</h1>
<table>
<thead>
<tr>
<th><strong>属性/方法</strong></th>
<th><strong>描述</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>HTMLElement.<strong>style</strong></td>
<td>style是一个对象,对应于css中的属性,属性是驼峰命名的,<strong>注意值带单位</strong>!</td>
</tr>
<tr>
<td>style.<strong>cssText</strong></td>
<td>设置<code>style</code>样式字符串值,同<code>html</code>标签中的<code>style</code>,<strong>注意</strong>会覆盖已有style样式</td>
</tr>
<tr>
<td>ele.<strong>className</strong></td>
<td>获取、设置class样式值(字符串)</td>
</tr>
<tr>
<td>ele.<strong>classList</strong></td>
<td>样式<code>class</code>列表,DOMTokenList集合,支持add/remove/toggle方法</td>
</tr>
<tr>
<td>length、value</td>
<td>数量,值(同<code>className</code>)</td>
</tr>
<tr>
<td>contains(css)</td>
<td>是否包含指定样式,返回<code>bool</code></td>
</tr>
<tr>
<td>add(...css)</td>
<td>添加(多个)样式</td>
</tr>
<tr>
<td>remove(...css)</td>
<td>移除(多个)样式</td>
</tr>
<tr>
<td>replace(old, new)</td>
<td>替换</td>
</tr>
<tr>
<td>toggle(css)</td>
<td>不存在就添加,存在就移除(toggle /ˈtɑːɡl/ 切换)</td>
</tr>
<tr>
<td>windwo.<strong>getComputedStyle</strong>(ele)</td>
<td>计算/获取一个元素的已解析(resolved)样式<code>style</code>对象(同<code>elem.style</code>)</td>
</tr>
</tbody>
</table>
<p>重置<strong>style</strong>属性样式的方式:</p>
<ul>
<li><strong>值置空</strong>:<code>cdiv.style.backgroundColor="";</code></li>
<li><strong>移除属性值</strong>:<code>cdiv.style.removeProperty("backgroundColor");</code></li>
</ul>
<pre><code class="language-html"><div id="cssDiv" class="c1 c2 c3 c4">css</div>
<script>
const cdiv = document.getElementById("cssDiv");
cdiv.style.backgroundColor = window.prompt("input background color", "red");
cdiv.style.backgroundColor = "";
cdiv.style.removeProperty("backgroundColor");
cdiv.style.lineHeight = "30px";//注意要带单位
cdiv.style.cssText = "color:red;font-weight:bold;" //会覆盖前面的样式
//计算样式
const cdstyle = getComputedStyle(cdiv);
console.log(cdiv.className); //c1 c2 c3 c4
console.log(cdiv.classList); //DOMTokenList(4) [ "c1", "c2", "c3", "c4" ]
cdiv.classList.toggle("c1");
cdiv.classList.remove("c1", "c2");
</script>
</code></pre>
<hr>
<h1 id="05滚动和坐标">05、滚动和坐标</h1>
<p>有效的<strong>文档窗口区域</strong>高度、宽度,可以使用 <code>document.documentElement</code> 的 <strong><code>clientWidth/clientHeight</code></strong>,不含滚动条。<strong>window.innerWidth/innerHeight</strong> 包括了滚动条。</p>
<p><img src="https://img2022.cnblogs.com/blog/151257/202211/151257-20221114203756394-908689376.png" alt="image.png" loading="lazy"></p>
<p><strong>文档完整大小</strong>(包含滚动隐藏的部分):documentElement.<strong>scrollWidth</strong>/<strong>scrollHeight</strong>,如果内容没有铺满,某些浏览器会小于clientWidth/clientHeight。因此获取完整文档高度,可以取多个值的最大值:</p>
<pre><code class="language-javascript">let scrollHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight,
document.body.offsetHeight, document.documentElement.offsetHeight,
document.body.clientHeight, document.documentElement.clientHeight);
</code></pre>
<p><strong>🔸滚动位置</strong>:</p>
<ul>
<li>window.<strong>scrollX</strong>/<strong>scrollY</strong>,一般就用这个就可以了。</li>
<li>window.pageXOffset /pageYOffset ,是上面的别称。</li>
<li>document.documentElement.scrollLeft/scrollTop</li>
</ul>
<p><strong>🔸滚动方法</strong>:方法更通用,兼容性更好。</p>
<ul>
<li>window.<strong>scrollBy</strong>(x,y) ,移动的距离。</li>
<li>window.<strong>scrollTo</strong>(pageX,pageY),移动到坐标。</li>
<li>ele.<strong>scrollIntoView</strong>(top),滚动到元素<code>ele</code>可见,参数top为bool,true(元素显示在顶部)、false(底部)</li>
</ul>
<p><strong>🔸禁止滚动</strong>:设置css属性<code>overflow </code>:<code>document.body.style.overflow = "hidden"</code>,可用于元素、document。</p>
<p><strong>🔸坐标</strong>:<strong><code>clientX/clientY</code></strong> 为相对于窗口的坐标,就是能看到的位置。<strong><code>pageX/pageY</code></strong>为相对于文档的坐标,包括滚动隐藏的部分。</p>
<p><img src="https://img2022.cnblogs.com/blog/151257/202211/151257-20221114203756429-144842605.png" alt="image.png" loading="lazy"></p>
<p><strong>🔸元素坐标</strong>:</p>
<ul>
<li>相对于窗口的坐标:elem.<strong>getBoundingClientRect</strong>(),返回一个 DOMRect 对象,包含了坐标位置宽(x、y、widht、height、top、left)等属性。</li>
<li>相对于文档的坐标:elem.getBoundingClientRect() 加上当前页面滚动<code>window.scrollX/scrollY</code></li>
<li>获取指定坐标的元素:document.elementFromPoint(x, y),获取坐标 (x, y) 处嵌套最多的元素。</li>
</ul>
<pre><code class="language-javascript">const cele= document.elementFromPoint(window.innerWidth/2,window.innerHeight/2);
cele.style.backgroundColor='red';
cele.scrollIntoView(true);
const rect = sdiv.getBoundingClientRect();
console.log(rect.x, rect.y, rect.left, rect.top); //13 260.875 13 260.875
</code></pre>
<hr>
<blockquote>
<p><strong>©️版权申明</strong>:版权所有@安木夕,本文内容仅供学习,欢迎指正、交流,转载请注明出处!<em>原文编辑地址-语雀</em></p>
</blockquote><br><br>
来源:https://www.cnblogs.com/anding/p/16890295.html
頁:
[1]