DOM笔记

301 阅读3分钟

一、DOM简介

网页其实是一个树

1.png

JS用document来操作网页,这就是Document Object Model 文档对象模型

二、获取元素的API

  • 获取任意元素

     window.idxxx // 或者直接idxxx
     document.getElementById('idxxx')
     document.getElementsByTagName('div')[0]
     document.getElementsByClassName('red')[0]
     document.querySelector('#idxxx') 
     document.querySelectorAll('.red')[0] //最后两个比较常用
    
  • 获取html元素

    document.documentElement
    
  • 获取head元素

    document.head
    
  • 获取body元素

    document.body
    
  • 获取窗口(窗口不是元素)

     window
    
  • 获取所有元素

    document.all//document.all是第六个false值(0,NaN,'',null,undefined)
    

三、获取元素的原型

获取到的元素是一个对象

3.1节点和元素的区别

节点Node包括以下几种,可以通过x.nodeType来得到

  • 元素Element,也叫标签Tag
  • 文本Text
  • 注释Comment
  • 文档Document等等

3.2一个div的完整原型链

2.png

四、节点的增删改查

4.1增加节点

  • 创建标签节点

    let div1 = document.createElement('div')
    
  • 创建一个文本节点

    text1 = document.createTextNode('你好')
    
  • 在标签里面插入文本

    div1.appendChild(text1)
    div1.innerText = '你好'
    div1.textContent ='你好'
    
    • 创建的标签默认处于JS线程中,必须放在body或者head才会生效

    • document.body.appendChild(div1)
      //或者页面已知元素.appendChild(div1)
      

Q:页面中有div#test1,div#test2,div会出现在哪里

let div = document.createElement('div')
test1.appendChild(div)
test2.appendChild(div)

A:出现在test2里,一个元素不能出现在两个地方,除非复制一份(cloneNode)

4.2删除节点

parentNode.removeChild//旧方法,通过父节点删除
childNode.remove()//IE不兼容

4.3修改节点

  • 修改属性
div.className = 'blue' //修改class
div.classList.add('red') //修改class
div.style = 'width:100px;color:blue' //修改style,全覆盖
div.style.width = '200px'//修改style的一一部分
div.style.backgroundColor = 'white' //用-隔开的全部用大写代替
div.dataset.x = 'frank' //修改自定义data-**的属性
  • 修改事件处理函数

    div.onclick默认null,但是如果改为一个函数,那么在点击的时候浏览器会调用这个函数

    调用是通过fn.call(div,event)

  • 修改文本内容

    div.innerText = 'xxx'
    div.textContent = 'xxx'
    
  • 修改HTML内容

    div.innerHTML = '<strong>重要内容</strong>'
    
  • 修改标签

    div.innerHTML = '' //先清空
    div.appendChild(div2)//再加内容
    
  • 修改父节点

    newParent.appendChild(div)
    

4.4查看节点

  • 查看父节点

    node.parentNode //node.parentElement
    
  • 查看父节点的父节点

    node.parentNode.parentNode
    
  • 查子字节

    node.childNodes//node.children,优先使用
    
    • 当子节点变化时,两者也会同时变化
  • 查兄弟节点

    node.parentNode.childNodes //node.parentNode.children,还要排除自己
    
    let siblings = []
    let c2 = div2.parentElement.children
    for(let i = 0;i<c2.length;i++){
        if(c2[i] !== div2){
            siblings.push(c[i])
        }
    }
    
  • 查看第一个子节点/最后一个子节点

    node.firstChild
    node.lastChild
    
  • 查看上一个兄弟节点/下一个兄弟节点

    node.previousSibling
    node.nextSibling
    
  • 遍历一个div的所有元素

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

五、DOM操作跨线程

5.1JS引擎渲染引擎

浏览器分为渲染引擎和JS引擎,两者各司其职,渲染引擎只能操作页面,JS引擎只能操作JS

document.body.appendChild(div1) //这句话如何改变页面
  • 当浏览器发现JS在body里面加了一个div1对象,会通知渲染引擎在页面里也增加一个div元素
  • 新增的div元素所有属性照抄div1对象
  • 对div1的多次操作,浏览器可能会合并成一次操作,也可能不会

3.png

  • 对div1的标准属性(id、className、title)或者data-**属性修改,会被浏览器同步到页面中

  • 对div1的非标准属性修改,会停留在JS线程中,不会同步到页面中

  • 如果有自定义属性,又想被同步到页面中,请使用data-作为前缀

5.2Property和Attribute

JS线程中的div1所有属性叫做property;渲染引擎中的div1对应标签的属性,叫做attribute

  • 大部分时候,两者相等
  • 如果不是标准属性,它们只会在一开始相等,attribute只支持字符串,property支持字符串、布尔类型