《DOM编程》

85 阅读5分钟
  1. DOM简介
    JS用document操作网页
    这就是Document Object Model文档对象模型
  2. 获取元素的API
    获取元素也叫标签
    很多API
    window.idxxx或者直接idxxx idxxx意思就是一个标签的id名字
    document.getElementById(‘id’)用来查找id
    document.getElementsByTagName(‘div’)[0] 用来查找所有div 这是一个伪数组
    document.getElementsByClassName(‘red’)[0] 用来查找所有属性名为red的伪数组
    document.querySelector(‘#id’)用来查找id
    document.querySelectorAll(‘.red’)【0】用来查找所有的red
  • 用哪一个
    工作中用querySelecter和querySelecterAll
    做demo直接用window.id
    要兼容IE的可怜虫才用getElement(s)Byxxx
  • 获取特定的元素
    获取html元素 document.documentElement
    获取head元素 document.head
    获取body元素 document.body
    获取窗口 (窗口不是元素)
    获取所有元素 document.all
    这个document.all 在除IE外浏览器功能正常使用 但是值却认为是假 是第六个falsy值
  1. 元素的六层原型链
    我们获取到的元素是一个对象 这个对象有六层原型
  • 节点元素区别
    节点Node包括以下几种
    MDN有完整描述
    x.nodeType得到一个数字
    1表示元素Element 也叫标签Tag
    3表示文本Text
    8表示注释Comment
    9表示文档Document
    11表示文档片段DocumentFragment
    记住1和3即可
  1. 创建元素的API

增:

创建一个标签节点
let div1=document.createElement(‘div’)
document.createElement(‘style’)
document.createElement(‘script’)
document.createElement(‘li’)

创建一个文本节点
document.createTextNode(‘你好’)

标签里面插入文本
div1.appendChild(text1)
div1.innerText=‘你好’或者div1.textContent=‘你好’
但是不能用div1.appendChild(‘你好’)

插入页面中
你创建的标签默认处于JS线程中
你必须把他插到head或者body里面 他才会生效
document.body.appendChild(div)
或者
已在页面中的元素.appendChild(div)

  • appendChild
    代码
    页面中有div#text1 和div1#text2
    let div=document.createElement(‘div’)
    text1.appendChild(div)
    text2.appendChild(div)
    请问最终div出现在哪里?
    答案:div出现在text2里面 因为一个元素不能出现在两个地方 除非复制一份
    cloneNode(true/false)克隆 深克隆或者浅克隆

两种方法:
旧方法:parentNode.childChild(childNode)
新方法:childChild.remove()

思考:

如果一个node被移出页面(DOM树)
那么他还能再次回到页面中吗?
答案是可以的 因为只是移出页面 但是还在内存里 所以还可以重新加回来
如果不想再次回来的话 删除之后 再赋值为null

  • 改属性:
    写标准属性:
    改class:div.className=‘red blue’(会覆盖原先的class)
    改class:div.classList.add(‘red’)
    改style:div.style=‘’但是这样改会直接覆盖原先所设置的所有
    所以如果只改一部分 div.style.color=‘red’
    大小写 background-color 在JS里应该写 backgroundColor
    读标准属性
    div.classList/a.href
    div.getAttribute(‘class’)/a.getAttribute(‘href’)
    两种方法都可以 但值可能稍微不同 麻烦的那种更保险

  • 改事件处理函数
    div.onlick默认为null
    默认点击div不会有任何事情发生
    但是如果你把div的onlick改写为一个函数fn
    那么点击div的时候,浏览器就会调用这个函数
    并且是这样调用的fn.call(div,event)
    div会被当做this
    event则包含了点击事件的所有信息,如坐标

    div.addEventLister
    是div.onclick的升级版

  • 改内容
    改文本内容
    div.innerText=‘XXX’
    div.textContent=‘XXX’
    两者几乎没有去区别 记住哪个用哪个

  • 改html内容
    div.innerHtml=‘重要内容
    改标签
    div.innerHtml=‘’先清空
    div.appendChild(div2)再加内容

  • 改爸爸
    想要找一个新爸爸
    newParent.appendChild(div)
    这样就从原来的地方消失了,之间变到新的地方去

  • 查看元素的API
    查爸爸:
    node.parentNode或者node.parentElement
    查爷爷
    node.parentNode.parentNode
    查子代
    node.childNodes或者node.children
    区别 第一个会把所有的空格也当成儿子 第二个则会只算元素
    这两个查询会实时更新,如果用queryS查询到的 后续再对数据进行变化 但查询结果不变
    查兄弟姐妹
    node.parentNode.childNodes还要排除自己 这个还要排除空格
    node.parentNode.children 还要排除自己

    查看下一个元素nextElementSibling
    查看老大
    node.firstChild
    查看最后一个
    node.lastChild
    查看上一个哥姐
    node.previousSibling
    查看下一个弟妹
    node.nestSibling 最后两个不会获取文本节点

  • 遍历一个div里面的所有元素

**

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

DOM操作跨线程

  • 跨线程操作
    各线程各司其职
    JS引擎不能操作页面,只能操作JS
    渲染引擎不能操作JS,只能操作页面
    document.body.appendChild(div1)
    这句JS是如何改变页面的
  • 跨线程通信
    当浏览器发现JS在body里面加了一个div对象
    浏览器就会通知渲染引擎在页面里也新增一个div元素
    新增的div元素所有属性都照抄div1对象
  • 插入新标签的完整过程
    在div1放入页面之前
    你对div1所有的操作都属于JS线程内的操作
    把div1放入页面之时
    浏览器会发现JS的意图
    就会通知渲染线程在页面中渲染div1对应的元素
    把div放入页面之后
    你对div1的操作都有可能会触发重新渲染
    对id的改动可能会重新渲染 也可能不会
    对title的操作 也可能会重新渲染 也可能不会
    如果你连续对div1多次操作,浏览器可能会合并成一次操作 也可能不会
    比如:对一个元素 写两个CSS样式 然后第二个样式改变宽度 然后用js为元素添加css样式 随后 两个样式会被合并成一次操作 并不会有动画效果
    但如果 在js添加两个样式之间 加上别的样式 比如 div.clientWith 获取宽度 在添加第二个样式 那样浏览器就会重新渲染 然后就会有动画效果 从原来的宽度过渡到200px
  • 属性同步
    标准属性
    对div1的标准属性的修改,会被浏览器同步到页面中
    比如id className title
    data-*属性
    同上
    非标准属性修改
    对非标准属性的修改,则只会停留在JS线程中
    不会同步到页面里
    比如x属性
    启示
    如果你有自定义属性,又想被同步到页面中去,请使用data-作为前缀 然后用dataset.后缀
  • property属性
    JS线程中div1的所有属性,叫做div1的property
    attribute也是属性
    渲染引擎中div1对应标签的属性,叫做attribute
    区别:
    大部分时候,同名的property和attribute值相等
    但如果不是标准属性,那么他俩只会在一开始时相等
    但注意attribute只支持字符串
    而property支持字符串布尔类型