DOM

112 阅读4分钟
DOM(文档对象模型)
  • 文档:一个页面就是一个文档,DOM中用 document 表示
  • 元素:页面中的所有标签都是元素,DOM中用 element 表示
  • 节点:网页中所有内容都是节点(标签、属性、文本、注释等),DOM中用 node 表示

获取元素
(1)根据 ID 获取
  • document.getElementById('元素id名'),获取带有 ID 的元素对象

  • 使用 console.dir(),可以打印我们获取的元素对象,查看对象里面的属性和方法

     var div = document.getElementById('box');
     console.dir(div);
    
(2)根据标签名获取
  • document.getElementsByTagName('标签名'),返回带有指定标签名的对象的集合,以伪数组形式存储

    • 得到的是一个对象的集合,要想操作里面元素就要遍历
    • 得到的元素对象是动态的
    • 如果获取不到元素,就返回空的伪数组
  • element.getElementsByTagName('标签名'),获取某个元素内部所有指定标签名的子元素

    • 父元素必须的单个对象(指明是哪个元素对象),获取的时候不包括父元素

       var lis = document.getElementsByTagName('li');
       var ol = document.getElementsById('ol');
       console.log(ol.getElementsByTagName('li')); // 打印 ol 下的 li 元素
      
(3)通过H5新增方法获取
  • document.getElementsByClassName('类名'),根据类名返回元素对象集合

     var div = document.getElementsByClassName('box');
    
  • document.querySelector('选择器'),根据指定选择器* 返回第一个元素对象*

     var div = document.querySelector('#nav');
    
  • document.querySelectorAll('选择器'),根据指定选择器返回所有元素对象集合

     var div = document.querySelectorAll('li');
    
  • 注意:第二个、第三个方法里的选择符需要加符号,如 #nav、.box

(4)特殊元素获取
  • document.documentElement,获取 html 元素对象

  • document.body,获取 body 元素对象

  • document.head

  • document.title,获取页面的标题,也可以修改标题

     var htmlEle = document.documentElement;
     var bodyEle = document.body;
     var headEle = document.head;
     var titleEle = document.title;
    

操作元素
(1)改变元素内容
  • element.innerText,从起始位置到结束位置的内容,会去除 html 标签,空格和换行也会去掉。 非标准
  • element.innerHTML,从起始位置到结束位置的内容,包括 html 标签,保留空格和换行。 W3C标准
(2)常用元素属性操作
  • element.src,src 可以换成 href、id、alt、title

     img.src = './bg2.png'; // 修改图片路径
     img.title = '背景2'; // 修改鼠标悬停显示的结果
    
(3)表单元素属性操作
  • type、value、checked、selected、disabled

     btn.disabled = true; // 表示按钮被禁用
     input.value = 'clicked'; // 修改 input 里的文字内容
    
(4)样式属性操作
  • element.style,行内样式操作

     div.style.backgroundColor = 'skyblue';
    
  • element.className,类名样式操作

     div.className = 'div'
    
  • 注意:

    • JS 里的样式采取驼峰命名法,如 fontSize、backgroundColor
    • JS 修改 style样式操作,产生的是行内样式,CSS权重高,为 1000

排他思想(算法)
  • 1、所有元素全部清除样式

  • 2、给当前元素设置样式

     var btns = document.getElementByTagName('button');
     // btns 得到的是伪数组,里面的每一个元素 btns[i]
     for(var i = 0; i < btns.length; i++){
         // (1) 先把所有按钮背景颜色去掉
         btns[i].onclick = function(){
             for(var i = 0; i < btns.length; i++){
                 btns[i].style.backgroundColor = '';
             }
             // (2) 再让背景颜色为 skyblue
             this.style.backgroundColor = 'skyblue';
         }
     }
    

自定义属性操作
(1)获取元素
  • element.属性

     console.log(div.id);
    
  • element.getAttribute('属性'),程序员之间添加的属性,如 index

     console.log(div.getAttribute('id'));
     console.log(div.getAttribute('index'));
    
(2)设置元素属性值
  • element.属性 = '值'

     div.id = 'test';
     div.className = 'navs';
    
  • element.setAttribute('属性','值'),主要针对自定义属性

     div.setAttribute('index',2);
     div.setAttribute('class','footer');  // class 特殊
    
(3)移除属性
  • removeAttribute(属性)

     div.removeAttribute('index');
    

H5自定义属性
  • H5 新增获取自定义属性的方法,只能获取 data- 开头的,ie11 以上使用

  • dataset 是一个集合,里面存放了所有以 data 开头的自定义属性

     console.log(div.dataset);
     console.log(div.dataset.index);
     console.log(div.dataset['index']);
    
  • 如果自定义属性里面有多个 - 相连的单词,获取时要采取驼峰命名法

     console.log(div.dataset.listName);  // 在 div 中是 data-list-name
     console.log(div.dataset['listName']); 
    

节点概述
  • 节点至少拥有 nodeType(节点类型)、nodeName(节点名称)、nodeValue(节点值)
  • 元素节点 nodeType 为 1,属性节点 nodeType 为 2,文本节点 nodeType 为 3(文本节点包括文字、空格、换行等)
  • 实际开发中,节点操作主要操作的是 元素节点
(1)节点操作之父节点
  • element.parentNode,得到的是里元素最近的父节点,找不到父节点就返回 null

     console.log(div.parentNode);
    
(2)节点操作之子节点
  • element.childNodes,获取所有的子节点,包括 元素节点、文本节点等

     console.log(ul.childNodes);
    
  • element.children,获取所有的子元素节点,实际开发使用的

     console.log(ul.children);
    
  • element.firstChild,获取第一个子节点,包括 元素节点、文本节点等

     console.log(ul.firstChild);
     console.log(ul.lastChild); // 获取最后一个子节点
    
  • element.firstElementChild,获取第一个子元素节点

     console.log(ul.firstElementChild); 
     console.log(ul.lastElementChild); // 有兼容性问题:ie9 以上支持
     ​
     // 实际开发写法,既没有兼容性问题又返回第一个子元素
     console.log(ol.children[ol.children[0]);
     console.log(ol.children[ol.chileren.length-1]); // 最后一个子元素
    
(3)节点操作之兄弟节点
  • element.nextSibling,下一个兄弟节点,包含元素节点、文本节点等

     console.log(ul.nextSibling);
     console.log(ul.previousSibling); // 上一个兄弟节点
    
  • element.nextElementSibling,下一个兄弟元素节点

     console.log(ul.nextElementSibling);
     console.log(ul.previousElementSibling); // 上一个兄弟元素节点
    
(4)节点操作创建和添加节点
  • document.createElement,创建元素节点

     var li = document.createElement('li');
    
  • node.appendChild(child),将一个节点添加到指定父节点的子节点列表末尾

     var li = document.createElement('li');
     ul.appendChild(li);
    
  • node.insertBefore(child,指定元素),将一个节点添加到父节点的指定子节点前面

     var lili = document.createElement('li');
     ul.insertBefore(lili, ul.childeren[0]);
    
(5)节点操作之删除节点
  • node.removeChild(child),删除父节点下的一个子节点,返回删除的节点

     ul.removeChild(ul.children[0]);
    
(6)节点操作之克隆节点
  • node.conleNode(参数)

    • 参数为空 或 false,则是浅拷贝,即只复制标签,不复制里面的内容
    • 参数为 true,则是深拷贝,复制所有内容

事件
事件基础
  • 事件三要素,由下面三部分组成

    • 事件源:绑定事件的页面元素
    • 事件类型:触发的什么事件
    • 事件处理程序(函数):事件触发后要执行的函数
  • 执行事件步骤

    • 获取事件源

    • 注册事件(绑定事件)

      • 语法: 页面元素.on+事件类型 = 函数

         btn.onclick = function () {}
        
    • 添加事件处理程序(采取函数赋值形式)

注册事件
  • (1)传统注册事件

     btn.onclick = function () { }
    
    • function 叫监听器
    • 特点:注册事件的唯一性,同一元素同一事件只能设置一个处理函数,最后注册的处理函数会覆盖前面注册的处理函数
  • (2)方法监听注册事件

     btn.addEventListener('click', function () { })
    
    • 里面的事件类型是字符串,必须加引号,且不带 on
    • 同一元素同一事件可以添加多个监听器(事件处理程序)
删除事件
  • (1)传统方式删除

     div.onclick = function () {
         console.log(110);
         // 在点击之后就会将该事件删除
         btn.onclick = null;
     }
    
  • (2)removeEventListener 删除事件

     div.addEventListener('click', fn); // fn b
     function fn(){
         console.log(110);
         // 在点击之后就会将该事件删除
         btn.removeEventListener('click', fn);
     }
    
DOM事件流三个阶段
  • 捕获阶段、当前目标阶段、冒泡阶段

  • JS 代码中只能执行捕获或冒泡其中一个阶段,onclick 只能得到冒泡阶段

  • addEventListener 第三个参数为 true,处于捕获阶段,document -> html -> body -> father -> son

     <div class="father">
         <div class="son">子盒子</div>
     </div>
     <script>
         var son = document.querySelector('.son');
         son.addEventListener('click', function () { 
             alert('son');
         });
         var father = document.querySelector('.father');
             father.addEventListener('click', function () { 
                 alert('father');
             });
         // 先弹出 father,再弹出 son
     </script> 
    
  • addEventListener 第三个参数为 false 或 省略,处于冒泡阶段,son-> father -> body -> html -> document

     <div class="father">
         <div class="son">子盒子</div>
     </div>
     <script>
         var son = document.querySelector('.son');
         son.addEventListener('click', function () { 
             alert('son');
         }, false);
         var father = document.querySelector('.father');
         father.addEventListener('click', function () { 
             alert('father');
         }, false);
         // 先弹出 son,再弹出 father
     </script>
    
事件对象
  • event 就是一个事件对象,写到监听函数的小括号里,当形参来看

  • 事件对象只有事件存在才会存在

  • (1)e.target,返回的是触发事件的对象

     ul.addEventListener('click', function (e) {
         // e.target 返回的是触发事件的对象(元素)
         console.log(e.target); // 点击 li,e.target 就指向 li
         // this 哪个元素绑定了这个事件,就返回谁
         console.log(this); // 给 ul 绑定了事件,this 就指向 ul
     })
    
  • (2)e.type,返回事件类型

     div.addEventListener('mouseover', function (e) {
         console.log(e.type); // mouseover
     })
    
  • (3)e.preventDefault(),阻止默认行为(事件),让链接不跳转 或 让提交按钮不提交

     a.addEventListener('click', function (e) {
         e.preventDefault(); // DOM 标准写法
     })
    
  • (4)e.stopPropagation()阻止事件冒泡

     <div class="father">
         <div class="son">子盒子</div>
     </div>
     <script>
         var son = document.querySelector('.son');
         son.addEventListener('click', function (e) {
             alert('son');
             e.stopPropagation(); // DOM 标准
             e.cancelBubble = true; // 非标准
         }, false);
         var father = document.querySelector('.father');
         father.addEventListener('click', function () { 
             alert('father');
         }, false);
         // 点击 son 就只弹出 son,因为停止冒泡了
     </script>
    
事件委托
  • 核心原理:给父节点添加监听器,利用事件冒泡影响每一个子节点

     var ul = document.querySelector('ul');
     ul.addEventListener('click', function(e) {
         e.target.style.backgroundColor = 'skyblue';
     })
    
鼠标事件
  • (1)contextmenu,禁用右键菜单

     document.addEventListener('contextmenu', function (e) {
         e.preventDeafult();
     })
    
  • (2)selectstart,禁止选中文字

     document.addEventListener('selectstart', function (e) {
         e.preventDefault();
     })
    
鼠标事件对象 MouseEvent
 document.addEventListener('click', function (e) {
     // 1、client,鼠标在可视区的 x 和 y 坐标,与 页面滚动无关
     console.log(e.clientX);
     console.log(e.clientY);
     // 2、page,鼠标在页面文档的 x 和 y 坐标
     console.log(e.pageX);
     console.log(e.pageY);
     // 3、screen,鼠标在电脑屏幕的 x 和 y 坐标
     console.log(e.screenX);
     console.log(e.screenY);
 })
键盘事件
  • (1)keyup,按键弹起时触发

     document.addEventListener('keyup', function () {
         console.log('弹起');
     })
    
  • (2)keydown,按键按下时触发,能识别功能键,如 ctrl、shift、左右箭头

     document.addEventListener('keydown', function () {
         console.log('我按下了down');
     })
    
  • (3)keypress,按键按下时触发,不能识别功能键

     document.addEventListener('keypress', function () {
         console.log('我按下了press');
     })
    
  • 执行顺序: keydown 、keypress 、keyup

键盘事件对象 KeyBoardEvent
  • keyCode,得到相应键的 ASCII码值

     document.addEventListener('keyup', function () {
         console.log(e.keyCode);
     })
    
  • keyupkeypress事件不区分字母大小写,a 和 A 得到的都是 65

  • keypress事件区分字母大小写