36- 【JS编程接口】DOM 编程的增删改查

本文深入讲解了使用JavaScript操作DOM的方法,包括获取、创建、插入、删除、修改元素及属性,以及遍历DOM树的技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


网页其实也是一棵树,Html标签为根节点,文字也是一个节点

js怎么操作网页?

浏览器给window加了个document,window.document可以拿到根节点,根节点里所有的元素,就可以用document来操作,DOM Document Object Model 文档对象模型

如何获取任意元素? Element 元素/标签Tag

window.id/id

做demo直接用

window.logo
logo

document.getElementById(‘id’)

不用加#号 和全局属性冲突时用

document.getElementById('logo')

document.getElementsByTagName(‘标签名’)[0]

是一个伪数组,可加下标索引

document.getElementsByTagName('div')[5]

document.getElementsByClassName(‘类名’)[0]

是一个数组,可加下标索引

document.getElementsByClassName('inited')[0]  //类不用加.

document.querySelector(’#id’)

id必须加# 获取第一个 选择器都可

document.querySelector('#logo')

document.querySelectorAll(’.inited’)[0]

是一个数组,可加下标索引,类加.,id加#

document.querySelectorAll('#logo')[0]

如何获取特定元素?

只获取HTML元素 document.documentElement

只获取head document.head

<head>…</head>

只获取body document.body

<body class="light-chip alternate-logo use-notifier win" style="--logo-color:rgba(238,238,238,1);">…</body>

获取窗口window

window虽然不是元素也不是标签,但是可以控制

Window {parent: Window, opener: null, top: Window, length: 4, frames: Window, …}

监听事件

window.onclick=()=>{console.log('hi')}

hi

获取所有元素:document.all

是第六个falsy值 常用于判断是否为ie浏览器

document.all?'真':'假'
"假"

获取的元素是对象,需要搞懂他的原型

div六层原型链

console.dir打出所有目录,查看原型链

console.dir(document.querySelectorAll('div')[5])
  • 一层原型:HTMLDivElement.prototype
  • 二层原型:HTMLElement.prototype
  • 三层原型:Element.prototype 所有XML\HTML标签
  • 四层原型:Node.prototype 所有XML\HTML标签,文本,注释等
  • 五层原型:EventTarget.prototype 活动目标
  • 六层原型:Object.prototype

节点Node有几种

1 标签 元素

3 文本 文字

8 注释

9 文档

11 文档片段

节点的增删改查

增加标签节点

let div1=document.createElement(‘div/script/li等等’)

let div5=document.createElement('div')

div5
<div>​</div>​

添加文本节点

let text1=document.createTextNode(‘你好’)

let c=document.createTextNode('你好')

c
"你好"

在标签里加内容

div1.appendChild(text1) Node接口 text1是变量

div1.innerText(“文本”) div1.textContent(“文本”) Element接口

div5.innerText='你好'

div5
<div>​你好​</div>​

div5.textContent='你好'

div5
<div>​你好​</div>​

div5.appendChild(c)

div5
<div>​你好​ "你好"</div>​

不可混用Node接口和Element接口,否则报错

let div7=document.createElement('div')

div7.appendChild('你好')
VM55442:1 Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
    at <anonymous>:1:6

把标签插入页面

document.body.appendChild(div5) 必须插入才显示

div5.style.xxx来修改部分样式

创建的标签默认显示在js内,只有插入到head,body中才有效

document.body.append(div5)

div5.style.color='red'
"red"
div5.style.position='fixed'
"fixed"
div5.style.top='0px'
"0px"

在这里插入图片描述

例子:把div5先插入页面中body,再插入head中,只会在head中显示,由于他只能有一个父亲,类比送子观音

深拷贝,把div5复制一份,可以同时在head body显示

div6=div5.cloneNode(true)
document.head.appendChild(div6)

老方法

parentNode.removeChild(childNode) 可返回,由于删的还存在内存中,链进入

div5.parentNode.removeChild(div5)
div5.parentNode.appendChild(div5)

新方法 不兼容IE

childNode.remove() 可返回,由于删的还存在内存中

div5.remove()

彻底删除

div5.remove()之后
div5=null

写标准属性

改id div5.id=‘div3’

加引号 给div里加id

改class div5.className=‘xx’

给div里加类,class关键字

div5.classList.add(‘red’)

得class=“red blue”

改style id.style=‘color:black’

会替换掉全部

改style部分内容 id.style.color=‘black’
大小写 id.style.backgroundColor=‘white’

其中-的,都省略-减号,加字母大写

改data-*属性 有- 的属性名
  • 向div5里添加,注意是分号 div5.setAttribute(‘data-x’,‘test’)
  • 查看data-*属性值:div5.dataset.x
  • 修改data-*属性值:div5.dataset.x=‘frank’
div5.setAttribute('data-x','test')

div5
<div style=​"position:​ fixed;​ top:​ 0px;​ font-size:​ 60px;​ color:​ black;​ background-color:​ white;​" id=​"divx" class=​"xx" data-x=​"test">​你好​</div>​
div5.dataset.x
"test"
div5.dataset.x='frank'
"frank"
div5.dataset.x
"frank"

读标准属性

div.classList/a.href 有时出错,例如a标签

**div.getAttribute(‘class’) a.getAttribute(‘href’)**更保险
a.href
"http://js.jirengu.com/xxx"
a.getAttribute('href')
"xxx

a.className
"name"
a.getAttribute('class')
"name"
改事件处理函数

onclick点击

默认是null,给onclick设成一个函数,点击时调用fn(this,event),浏览器点击,用call传进来的

div5.onclick=function(){console.log(this);console.log(x)}

div.addEventListener监听多个

改内容
  • 改文本内容 div5.innerText=‘修改’ div5.textContent=‘修改2’
  • 改标签内容 **div5.innerHTML ** 但是也限制不能过多
div5.innerHTML='<strong>加粗</strong>'
  • 改标签 先清空div5.innerHTML=’'再加内容div5.innerText=‘哈哈哈哈’
改爸爸

新的父亲节点.appendChild(子元素)

div5
let div2=document.createElement('div')

div2.appendChild(div5)

查爸爸

div5.parentNode或者div5.parentElement

查爷爷

div5.parentElement.parentElement

查后代

x.children 常用这个,不含文本节点,删除后长度变

x.childNodes 会把空格文本算进去,删除后长度变

x.querySelectorAll(‘li’).remove 删除后不会改变长度

<ul id='x'>
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul>


x.children.length
3
x.childNodes.length
7

查兄弟姐妹

node.parsentNode.childNodes 包含自己和空格文本

node.parsentNode.children 包含自己

获取兄弟姐妹两个步骤:获取到父亲所有的孩子,在所有孩子中排出自己

a=[]
let arr=div5.parentNode.children
console.log(arr)
console.log('----')
for(let j=0;j<arr.length;j++){
if(arr[j]!==div5){
a.push(arr[j])
}
}

a
[div]

查看老大 div2.firstChild

查看老么 div2.lastChild

查看上一个元素哥哥 div4.previousElementSibling

只有元素 不带Element含有文本空格

参看下一个元素弟弟 div5.nextElementSibling

只有元素 不带Element含有文本空格

遍历div中所有元素 递归

let travel=(node,fn)=>{
fn(node)
if(node.children){
for(let i=0;i<node.children.length;i++){
travel(node.children[i],fn)
}
}
}

travel(div2,(node)=>console.log(node))

DOM操作跨线程

js引擎只能操作js,如document对象

渲染引擎只能操作页面,如Html.css

但是document.body.appendChild(‘div’)这个js怎么操作页面的呢?

跨线程通信

  • 浏览器发现js在body里加一个div对象
  • 便通知渲染引擎在页面上加div元素,是浏览器渲染的,不是js渲染的
  • 然后新增的元素的属性都照搬div对象

分析跨线程操作

所以浏览器通知会浪费时间,但是也方面单个优化

let div1=document.createElement('div')
div1.textContent='哈喽'

document.body.appendChild(div1)

div1.textContent='嘻嘻嘻'

插入新标签div1的全部过程

  • 放入页面之前:前两个操作只会在js执行线程里操作

  • 放在页面之时:浏览器发现js线程要向body里加div1,于是通知渲染线程在页面渲染div1对应的元素

  • 放入页面之后://浏览器通知渲染线程修改页面内容,可能会触发重新渲染

    div.id=‘newId’ 单操作可能重新渲染

    dib.title=‘new’ 单操作可能重新渲染

    多次操作div,可能合并成一个操作,比如动画:x.clientWidth触发重新渲染

    .start{
      width: 200px;
      height: 100px;
      border:1px solid red;
      transition:width 1s;
    }
    .end{
      width: 100px;
    }
    
    x.classList.add('start')
    x.clientWidth//这条可以实现动画显示,避免渲染合并
    x.classList.add('end')
    

属性同步

<div id="test" x="test" data-x="test">

let div1 = document.querySelector('#test')
div1.id = 'frank' // 同步过去了
div1.dataset.x = 'frank' // 同步过去了
div1.x = 'frank' // 没有同步过去
div1.style.border = '1px solid red'
    
<div id="frank" x="test" data-x="frank">//结果是x改变
标准属性

修改会被浏览器同步到页面中 如className、title、id

data-*属性

修改会被浏览器同步到页面中

非标准属性

修改后不会被浏览器同步到页面上,只会留在js线程里

启发

非标准属性前面加data-做前缀

properties VS attributes

prototype属性:js里的div的所有属性,常是对象的,如style,id…

attribute属性:渲染引擎中div对应标签属性,比如id='字符串'这条是属性

区别:同名基本相等,如果不是标准属性,开始时相等,修改后不一定相等

​ attribute只支持字符串,property支持很多类型

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值