DOM编程

186 阅读5分钟

网页是一棵树

1632878270(1).png

JS如何操作这棵树

  • 浏览器往window上加一个document即可
  • document就是这个网页的整体
  • JS把document作为对象进行操作

JS用document操作网页

  • 这就是document Object Model文档对象模型

1632878601(1).png

获取元素,也叫标签

  • 有很多API
  1. window.idXXX或者直接idXXX (可以直接idXXX)
  2. document.getElementById('idxxx')
    • 如果上面的id是全局变量,只能用这个
    • 不要用
  3. document.getElementsByTagName('div')[ 下标(0,1,2,3)]
    • 获取所有div标签,下标筛选定位某一个
    • 不要用
  4. document.getElementsByClassName('red')[ 下标(0,1,2,3)]
    • 获取所有类名为red的标签,下标筛选定位某一个
    • 不要用
  5. document.querySelector('#idxxx')
  6. document.querySelectorAll('.red')[同理]
  • 用哪一个
  1. 实际开发中,用querySelctor和querySelectorAll
  2. 做demo直接用idxxx,(可能导致沟通障碍,某些人不懂)
  3. 只有要兼容IE才会用getElement(s)ByXXX

小实操

  • 找到某个标签

1632901664(1).png

大于号可以省略,规则大部分参照css选择器功能,找到div里面第二个span标签,邮件reveal in elements panel 可以找打这个标签所在代码中的位置

  • 找到所有标签

1632901615(1).png

  • 补充:以上两种代码后面可以加[],数组下标

获取特定元素

获取html标签document.documentElement

1632902108(1).png
获取标签名竟然是大写

获取head元素

  • document.head

获取body元素

  • document.body

获取窗口元素(窗口不是元素)

1632902398(1).png
window虽然不是标签,但是某些情况下用于获取到然后添加一些全局的事件监听

获取所有元素

  • document.all

1632903136.png

  • 特别之处: document.all最初是IE浏览器中的,但是其他浏览器为了区分,把这句话的值设置为falsy值(即为假值),如图IE浏览器中为真值,但是到其他浏览器中就是假值,通常用来检测是否需要兼容IE
  • 但是 不影响这句话的使用 1632903755(1).png

获取到的元素是什么?

  • 获取的元素是对象 例:

1632904191(1).png

  • console.dir(div)看原型链

各层原型链

  1. 第一层原型 HTML.DivElement.prototype
    • 这里面是所有div标签共有属性
  2. 第二层原型 HTMLElement.prototype
    • 这里面是所有HTML标签共有的属性
  3. 第三层原型 Element.prototype
    • 这里面是所有XML,HTML标签的共有属性,相对于HTML以上层级的一类
  4. 第四层原型 Node.prototype
    • 这里面是所有节点共有的属性,节点包括XML标签文本注释、HTML标签文本注释等
  5. 第五层原型 EventTarget.prototype
    • 里面最重要的属性是addEventListener
  6. 最后一层原型就是Object.prototype

div 完整原型链(自身属性和共有属性)

image.png

节点元素区别??

节点Node包括以下几种

MDN有完整描述,x.nodeType得到一个数字

  • 1表示元素Element,也叫Tag
  • 3表示文本Text
  • 8表示注释Comment
  • 9表示文档Document
  • 11表示文档片段DocumentFrament
  • 记住1和2即可

节点的增删改查

  • 创建一个标签节点

1632969337(1).png

  • 创建一个文本节点

011353428d582211b9dd7cd5b4f321f.png

  • 标签里面加文本

image.png

注意!!

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

appendChild

  • 页面中有div#test和div#test2
  • let div=document.createElement('div')
  • test1.appendChild(div)
  • test2.appendChild(div) 结果 :最终在test2里面,一个元素不能在两个地方,除非复制一份,
  • 方法:.cloneNode
  • 官方文档参考developer.mozilla.org/zh-CN/docs/…

两种方法

  • 旧方法: parentNode.Child(childNode)
  • 新方法:childNode.remove()

注意:删除的内容还是保存在JS中,还可以再次调用

1632980041(1).png

思考

如果node被移出页面(Dom)树,那么他还会再次回到页面中吗?

答:依然在内存中,还是可以再次调用的除非先移除,再赋值为null,断开与内存的连接

改属性

写标准属性

  • 改class: div.className='red' 因为直接赋值会导致类名覆盖
    • 如果之前的是blue会覆盖,如果不覆盖只能写成+='空格red'
  • 改 class: div.classList.add('red') 不会覆盖
    • 意思是在类名列表里面加一个red类名
  • 改style:div.style='width:100px;height:100px;......'
  • 改style一小部分:div.style.width='200px' -改data-*属性:div.dataset.x='frank'几乎很少用到

读标准属性

  • div.class/div.id/a.href
  • div.getAttibute('class')/a.getAttribute('href')
  • 小区别
    • a.href,当href为相对路径的时候,JS会将网页链接加在后面,造成错误
    • 所以第二种方法获取的href更加准确,但是大部分情况下比如获取id,classname等,两种方法没有什么区别

改事件处理函数

div。onclick默认值为null

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

改内容

改文本内容

  • div.innerText='xxx'
  • div.textContent='xxx'
  • 两者没有任何区别

改HTML内容

  • div.innerHTML='XXX ' 里面可以加一些标签,实现某些效果

改标签

  • div.innerHTML='' //先清空
  • div.appendChild(div2)//再加内容

改父级

  • 找新父级
  • newParent.appenedChild(div)
  • 这样直接从原来的地方消失

查父级

  • node.parentNode或者node.aprentElement

查父级的父级

  • node.parentNode.parentNode

查子代

  • node.childNodes或者node.children(推荐使用)

查同级

  • node.parentNode.childNodes 还要排除自己,而且还要排除文本节点,更麻烦
  • node.parentNode.children 还要排除自己
  • 例:

e335021ff759104d9571c8dee8901cb.png
引入一个空数组siblins,引入变量c2,先获得父级的所有元素,再获得父级的子集元素,循环法,排除自己

查看第一个

  • 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))

小结:调用node可能会得到文本数据,如果后面加element可以直接得到元素