【原生DOM】DOM编程

185 阅读4分钟

DOM编程

目录

  • 前置知识
  • 网页就是一棵DOM树
  • JS如何操作这棵树
  • DOM元素
  • 节点的增删改查
  • DOM操作是跨线程的
  • Property VS Attribute

一、前置知识

  1. 理解简单的JS语法
  2. JS的七种数据类型:number、string、bool、symbol、undefined、null、Object
  3. JS五个falsy值:''、undefined、null、0、NaN
  4. 简单的CSS布局

二、网页是一棵DOM树

  • 代码+图解
DOM树

文字1

文字2

文字3文字4文字5

``` ![](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/58f91739ea494b588c647244f3829db2~tplv-k3u1fbpfcp-watermark.webp)

三、JS如何操作这棵树?

  • 使用document操作网页
  • 这就是DOM(Document Object Model)文档对象模型

四、DOM元素

  • 获取元素(标签)
    
    document.getElementById('xxx');
    .
    document.getElementsByTagName('div')[0];
    .
    document.getElementsByClassName('red')[0];
    .
    document.querySelector(''); | 需要遵守选择器的样式书写 如:'#id_1''.class_1'、
    .
    document.querySelectorALL(); |同上
    
  • 获取特定元素
      1、获取html元素
        document.documentElement
    
      2、获取head元素
        document.head
    
      3、获取body元素
        document.body
    
      4、获取窗口 |窗口不是元素
        window
    
      5、获取所有元素
        document.all  
    
    window.all: 是第6个falsy值 原因:因为window.all最早是IE发明的,早期的前端为了区分IE和其他浏览器,就一般如下设置。为了区分是IE还是非IE浏览器。
    if(window.all){
      console.log("这些代码只能在IE里面运行");
    }
    else{
      console.log("这些代码只能在非IE里面运行");
    }
    

  • 问题来了:获取到的元素到底是个啥?
    1. 显然获取到的元素是个对象
    2. 抓一只div对象来看看都有啥
       console.dir(div);
      
    3. div的6层原型链

  • 节点?元素?傻傻分不清楚

    使用 nodeType方法可以打印出节点的值

    1. 1表示元素ELement,也叫标签Tag
    2. 3表示文本Text
    3. 8表示注释Comment
    4. 9表示文档Document
    5. 更多节点值

五、节点的增删改查


1、增

  • 创建一个标签节点
    let div1=document.createElement('div');
    document.createElement('style');
    document.createElement('script');
    document.createElement('li');
    
  • 创建一个文本节点
    text1=document.createTextNode('你好');
    
  • 插入创建的节点:坑1:一个元素不能同时出现在(插入)两个地方,除非复制一份。
    div1.appendChild(text1); | 在div1标签里面插入文本节点text1
    
    document.body.appendChild(div1); | 在body里面插入div1标签
    
    document.head.appendChild(div1); | 在head里面插入div1标签
    

2、删

  • 删除节点:坑2:删除之后的节点被移除DOM树,但还在内存中,依然可以调用它再将其添加回来
    旧方法 | parentNode.removeChild('待删除的儿子节点')
    
    新方法 | 待删除的节点.remove();
    

3、改

  • 写标准属性:注意:js中不识别'-'这个字符,所以遇到'-'就将'-'后面第一个字母大写,如:background-color --> backgroundColor
    class | div.style.className='red blue'; --> 全覆盖
    改class | div.classList.add('red');
    改style | div.style='width:100px;color:blue'; --> 全覆盖
    改style | div.style.width='200px'; --> 推荐
    改data-*属性 | div.dataset.x='frank';
    
  • 读标准属性:下面两种方法都可以读属性,但某些情况下的值可能会不同。
    默认方法 | div.classList/a.href
    getter/setter方法 | div.getAttribute('class')/a.getAttribute('href');
    
  • 改文本内容
    div.innerText='你好,世界!';
    div.textContent='你好,世界!';
    
  • 改HTML内容
    div.innerHTML='<strong>重要的内容</strong>';
    
  • 改标签
    div.innerHTML=''; | 先清空内容
    div.appendChild(div2); | 再添加内容
    
  • 改父元素?
    newParent.appendChild(div); | div的父元素变成newParent,并且从原来的地方消失。
    

4、查

  • 查爸爸
    node.parentNode | node.parentElement
    
  • 查爷爷
    node.parentNode.parentNode
    
  • 查子代:坑1:当子代变化时,两者也会实时变化,例如遍历的数组长度length
    node.childNodes | node.children
    
  • 查兄弟姐妹
    node.parentNode.childNode | 注意要排除自己
    node.parentNode.children | 注意要排除自己
    
  • 查看老大、老幺
    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(div,(node)=>{
      console.log(node);
    })
    

六、DOM操作是跨线程的

  • 跨线程操作

    1. JS引擎不能操作页面,只能操作JS
    2. 渲染引擎不能操作JS,只能操作页面
    3. 例如执行如示代码:document.body.appendChild(div1) JS 是如何改变页面的?
  • 跨线程通信

    1. 当浏览器发现JS在body里面加了一个div对象
    2. 浏览器就会通知渲染引擎在页面里也新增一个div元素
  • 插入新标签的完整过程

    1. 在div1放入页面之前
       对div1进行的所有操作都是在JS线程中进行的
      
    2. 在div1放入页面之时
       浏览器发现了JS的意图,通知渲染线程在页面中渲染div1对应的元素
      
    3. 把div1放入页面之后
       当你想对div1再次进行操作时,都会有可能触发重新渲染
      
  • 属性同步

    1. 标准属性:如id,className,title等
    2. data-*属性
    3. 非标准属性:除开1,2两点的其他自定义属性
    4. 自动属性同步
    JS Bin

    id 一开始为 test,后来改为 frank

    你会发现页面中 id 变为 frank

    data-x 属性一开始为 test,后来改为 frank

    你会发现页面中的 data-x 变成了 frank

    x 属性一开始为 test,后来改为 frank

    你会发现页面中的 x 还是 test

    ``` ![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7ab8f5b146ed4d37947c1ab9b1c785a6~tplv-k3u1fbpfcp-watermark.webp)

七、Property VS Attribute

  • property属性

    JS 中div1的所有属性,叫做div1的property

  • attribute属性

    渲染引擎中div1对应标签的属性,叫做attribute

  • 二者的区别

    1. 大部分时候,同名的property和attriubte值相等。
    2. 但如果不是标准属性,两者的值只会在一开始的时候相等
    3. attribute: 只支持字符串类型
    4. property: 支持字符串、布尔等类型