DOM 课件

dom

文档对象模型(document object model);

浏览器中,最大的对象是 window,它之下有很多下级对象负责具体的事宜,document 是其中最重要的。

对象的属性还可以是对象,文档中的对象就是html中的元素,元素对象形成的结构是树形结构。

dom提供了可供使用的接口(api),js通过访问这些接口来完全操控文档。

W3C DOM 标准被分为 3 个不同的部分:

  • 核心 DOM - 针对任何结构化文档的标准模型

  • XML DOM - 针对 XML 文档的标准模型

  • HTML DOM - 针对 HTML 文档的标准模型

dom级别

DOM0 其实并没有一种标准叫“DOMLevel 0”,这只是DOM历史中的一个参照点。DOM0可以看做是IE4和Netscape Navigator 4中最初支持的DHTML。

内容 DOM0级事件具有极好的跨浏览器优势,会以最快的速度绑定。 为某一个元素的同一个行为绑定不同的方法在行内会分别执行。 为某一个元素的同一个行为绑定不同的方法在script标签中后面的方法会覆盖前面的方法。

删除DOM 0事件处理程序,只要将对应事件属性设为null即可。

DOM1 DOM1一般只有设计规范没有具体实现,所以一般跳过。

DOM2 对最初DOM的扩展增加了对鼠标和用户界面事件、范围、遍历(迭代DOM节点的方法)的支持,而且通过对象接口支持了层叠样式表(css)。另外DOM 1中的DOM Core 也被扩展以包含对XML命名空间的支持。

内容 DOM2新增以下模块,以支持新的接口。

DOM视图:描述追踪文档不同视图的接口 DOM事件:描述事件及事件处理的接口 DOM样式:描述处理元素css样式的接口 DOM遍历和范围:描述遍历和操作DOM树的接口 DOM2级事件是通过addEventListener绑定的事件,IE下的DOM2事件通过attachEvent绑定;可以给某一个元素的同一个行为绑定不同的方法在行内会分别执行。 DOM3进一步拓展了DOM,增加了以统一的方式加载和保存文档的方法(包含在一个叫DOM Load Save 的新模块中),还有验证文档的方法(DOM Validation)。

内容 DOM3级事件在DOM2级事件的基础上添加了更多的事件类型,全部类型如下:

事件类型 说明 举例 UI事件 当用户与页面上的元素交互时触发 load,scroll 焦点事件 当元素获得或失去焦点时触发 focus,blur 滚轮事件 当使用鼠标滚轮或类似设备时触发 mousewheel 鼠标事件 当用户通过鼠标在页面执行操作时发生 dbclick,mouseup 文本事件 挡在文档中输入文本时触发 textinput 变动事件 当底层DOM结构发生改变时触发 DOMsubtreeModified 合成事件 当为IME输入字符时触发 compositionstart 键盘事件 当用户通过键盘在页面上执行操作时触发 同时DOM3级事件也允许开发人员自定义一些事件。

目前,W3C不在按照Level来维护DOM了,而是作为DOM Living Standard 来维护,其快照成为DOM4.

如何获取文档元素的引用

  • getElementById()

  • getElementsByClassName()

  • getElementsByTagName()

  • querySelector()

  • querySelectorAll()

    var ele = document.getElementsByClassName('abc');
    //ele是一个集合,js没有集合的概念,js只有数组没有集合,但是集合和数组的解构很类似。
    //我们可以使用循环去遍历它,也可以使用部分数组的方法来操作它,但不是全部(forEach不可以)。
    for (var i = 0; i < ele.length; i++) {
      ele[i].style.border = '1px solid green';
    }

getElementById()只能由document发起,其他可以由document或具体的元素发起。

getElementById()、querySelector()返回元素,其他方法返回集合,js只有数组没有集合,但是集合和数组的解构很类似。我们可以使用循环去遍历它,也可以使用部分数组的方法来操作它,但不是全部(forEach不可以)。

节点操作

dom操作中,尽量减少页面的交互,dom操作尽量在内存中完成。

  • 创建

        //创建
        var newNode = document.createElement('li');
        var txtNode = document.createTextNode('新的');

    可以创建元素节点、文本节点。

  • 添加

        ul.insertBefore(newNode, ul.children[3]);
        ul.appendChild(newNode);

    insertBefore() 必须有2个参数,如果需要插入到最后,第二参数可以使用null或未定义。

    因为大多数情况下,需求都是插入到最后,所以appendChild用的机会会更多。

  • 克隆

    newNode.cloneNode(true)

    cloneNode() 的参数是布尔类型,默认是false,表示是否深度克隆。

    元素自身、元素的属性、元素的事件、元素的内容。

    浅克隆:元素自身、属性

    深克隆:元素自身、属性、子孙节点

    无论深克隆还是浅克隆,事件都不会被克隆。

  • 替换

        ul.replaceChild(new2, ul.children[3]);

    大多数节点操作都是由父元素发起。

  • 移除

        ul.removeChild(ul.children[3]);//标准dom
        ul.children[3].remove();//html dom

标准dom 、htmlDOM 、 xmlDOM

节点的遍历

  • 向上遍历

    parentElement parentNode

  • 同胞遍历

    • 向前 previousElementSibling prevSibling

    • 向后nextElementSibling nextSibling

  • 向下遍历

    • 所有 children childNodes

    • 第一个 firstElementChild firstChild

    • 最后一个lastElementChild lastChild

元素节点的属性操作

  • 通用的属性操作方法:

    • setAttribute(name,value) 设置属性

    • getAttribute(name) 读取属性的值

    • removeAttribute(name) 移除属性

    • hasAttribute(name) 判断是否有某个属性(返回布尔值)

  • 系统认可的(id、src、title、href)元素.id = ''

  • h5推荐的属性操作

    在html5中,自定义属性建议以data-*的形式,对应的,js也有固定的操作方法。

    元素.dataset.abc = 123; // 为元素添加属性data-abc,值是123;

    dataset基本可以替代通用属性操作(通用的属性操作不可控)。

  • css相关的

    • class属性:

    className 可读可写的属性,className属性会将class的值当成字符串整体进行操作。

    元素.className = 'a b c';//整体更新class属性的值

    classList属性可以进行更精细的操作

    元素.classList.add();//添加样式类
    元素.classList.remove();//移除样式类

    • style属性:

      style.cssText

        h1.style.cssText = 'colon:red;background-color:yellow'
        h1.style.cssText = 'color:red;'//整体替换

    style.css属性名称

        const h1 = document.querySelector('h1');
    ​
        h1.style.cssText = 'colon:red;background-color:yellow'
        h1.style.color = 'red';
        h1.style.backgroundColor = 'blue';
    //这种方式不会覆盖之前的样式

  • 获取元素的渲染样式值(经过浏览器计算后的样式值)

        function getStyle(ele, name) {
          if (ele.currentStyle) {
            return ele.currentStyle[name];//ie
          } else {
            return getComputedStyle(ele, null)[name];//w3c,第二参数是获取伪类
          }
        }

    我们获取到的样式值,通常都是类似8px这样的字符串,不能直接参数数学运算,应当使用如下方法做转换:

    parseFloat();//转为浮点数
    parseInt();//转为整数
    //从字符串的开始位置向后查找,找到最长的符合条件的数字转换,如果开始就不是数字,则返回NaN。

  • 操作元素内容

    ele.innerHTML;
    ele.outerHTML;
    ele.innerText;
    ele.outerText;

    例如ele是<h1></h1>;

    innerHTML ==> <h1>内容</h1>

    innerText ==> <h1>内容</h1>;//内容不经过html的解析;

    outerHTML ==> 内容

    outerText ==> 内容;//内容不经过html的解析;

  • 获取元素的系统值

    offsetclientscroll
    尺寸元素的边框、内边距、自身的总尺寸元素的内边距、自身的总尺寸(元素可以显示内容的区域尺寸)元素内容实际占用的尺寸,还需要加入元素的内边距。
    位置假设元素是绝对定位,相对于自身定位参照元素的偏移值元素左、上边框的宽度(没用)元素内容被滚动出显示范围的尺寸

    尺寸:width、height

    位置:left 、top

    用offset和client获取整个网页的尺寸时,不同的浏览器会出现差异,当网页的实际高度小于浏览器窗口高度时,有的浏览器认为offset尺寸有最小值(浏览器窗口的高度),另外的认为client有最小值(浏览器窗口的高度)。

  • 表单相关

    表单元素的值统一使用value属性(可读可写)。

    单选:选中项的值可是使用类似form.gender.value的形式来获取:

    <form>
        <div>
        性别:
          <label>
            <input type="radio" name="gender" value="male">
            男
          </label>
          <label>
            <input type="radio" name="gender" value="female">
            女
          </label>
        </div>
        <button type="submit">按钮</button>
      </form>
      <script>
        var form = document.forms[0];
    ​
        form.onsubmit = function () {
          console.log(form.gender.value);//获取选中项的值
          return false;
        }
    ​
      </script>

    复选

        <div>
          爱好:
          <label>
            <input type="checkbox" name="hobby" value="1">
            电子竞技
          </label>
          <label>
            <input type="checkbox" name="hobby" value="2">
            视觉艺术
          </label>
          <label>
            <input type="checkbox" name="hobby" value="3">
            学习
          </label>
          <label>
            <input type="checkbox" name="hobby" value="4">
            美食
          </label>
          <label>
            <input type="checkbox" name="hobby" value="5">
            旅游
          </label>
        </div>
        <button type="submit">按钮</button>
      </form>
      <script>
        var form = document.forms[0];
    ​
        for (var i = 0; i < form.hobby.length; i++) {
          form.hobby[i].onchange = hobby_change;
        }
    ​
        form.onsubmit = function () {
          // console.log(form.gender.value);
    ​
          //判断复选选了几个?
          var n = 0;
          for (var i = 0; i < form.hobby.length; i++) {
            if (form.hobby[i].checked) {
              n++;
            }
          }
          console.log(n);
    ​
    ​
    ​
          return false;
        }
    ​
        function hobby_change() {
          var n = 0;
          for (var i = 0; i < form.hobby.length; i++) {
            if (form.hobby[i].checked) {
              n++;
            }
          }
          console.log(n)
          if (n > 4) {
            this.checked = false;
          }
          if (n < 2) {
            this.checked = true;
          }
        }
      </script>

    复选的form.hobby是一个简单的集合,要判断选中几个,只能遍历,通过checked属性是否为true来判断,checked属性可读可写,我们可以通过为这个属性赋值来改变选中状态。

    复选的验证分为提交前验证和提交时验证:

    • 提交前:限制它选择的数量

      • 遍历每个选项,为每个选项附加change事件

      • 在change事件中统计选中数量。

      • 当选中数量不符合要求时,可以改变当前选中项的选中状态(checked属性赋值)。

    • 提交时:计算选中了几个

    select下拉菜单:

    新建: new Option(txt,value);
    ​
    插入:select.add(newOption);
    ​
    移除:select.remove(index)、select[index].remove();
    ​
            select.oprions.remove(index)、select.oprions[index].remove();
    ​
            select.length可以重新赋值来批量移除。

文档元素对象的内容操作

事件

DOM 1级(DOM Level 1)于1998年10月成为 W3C 的推荐标准,DOM1级由两个模块组成:DOM核心(DOM Core)和 DOM HTML,DOM Core 能映射以XML为基础的文档结构,允许获取和操作文档的任意部分,而DOM HTML 通过添加 HTML 专用的对象与函数对 DOM Core 进行了扩展。简单说,DOM1级就是映射文档结构和提供基本的文档操作方法。

DOM2级,就是对DOM1级进行扩展,2级DOM通过对象接口增加对鼠标和用户界面事件、范围、遍历和重叠样式表(CSS)的支持。同时也对DOM1进行了扩展,从而可支持XML命名空间。简单来说,DOM2级就是在DOM1的基础上增加了视图、事件、样式、遍历和范围的接口,和支持XML命名空间。

DOM3级,在前面DOM基础上,引入了以统一方式加载和保存文档的方法,新增了验证文档的方法,同时也对DOM核心进行了扩展,开始支持XML1.0规范。

除了上面的三个等级之外,还有一个叫DOM0级的东西,实际上标准并没有这个东西,它指的是IE4和Netscape Navigator 4.0 最初支持的DHTML,DHTML实际上是HTML、CSS和JS的一个集成,代表的是一种已有的技术,不是标椎,所以DOM0级其实代表的是历史节点中未形成标准的一个初期产物。

dom事件分为dom0、dom2:

dom0级规定元素可以采用属性的方式来附加事件的处理函数:

  <h1 οnclick="alert(123)">这是一段文字</h1>
​
  <script>
    var h1 = document.querySelector('h1');
​
    h1.onclick = () => {
      this;
    }
​
    h1.onclick = function () {
      this;
    }
​
  </script>

如果采用箭头函数,要注意,箭头函数的this指向定义时的作用域,在上例中,this指向window。而不同函数的this指向h1。

dom0级的事件处理函数,只能保留最后一个,之前的会被覆盖。如果要移除,为事件赋值null或空函数都可以。

dom2级,

    h1.addEventListener('click', abc);
    h1.addEventListener('click', function () {
      alert(789);
    })

可以使用addEventListener(事件名称,处理函数)的方法来添加新的监听者。新增的监听者不会覆盖之前的,也不会影响dom0的事件。

如果添加的监听者是匿名函数,则永远无法移除。如果是有名称的函数,可以使用removeEventListener(事件名称,处理函数名称)来移除。

    h1.addEventListener('click', function () {
      alert(789);
    })
    h1.removeEventListener('click', abc);
​
    //不能通过再写一遍匿名函数来达到移除的目的,因为,再写的函数是新函数,不指向原有函数!!
    h1.removeEventListener('click', function () {
      alert(789);
     });
​
    function abc() {
      alert(456);
    }

dom2级的事件建议在我们自己写js插件时,为了避免覆盖其他的插件效果,采用dom2的方式附加事件的处理函数。

事件对象

事件被触发时,会向函数传递一个event对象,我们可以直接使用:

    var e = e || event;

因为ie和w3c的获取形式不同,为了兼容ie,采用上述方法获得。

事件对象保存了事件发生时的状态,通过属性表现出来,事件对象还有一些方法可以起到控制事件的作用。

  • event.stopPropagation() 阻止事件的传递。

  • event.preventDefault() 阻止与事件关联的默认动作

  • event.clientX event.clientY 获取事件发生时鼠标相对浏览器窗口的偏移值(简写为e.x,e.y)。

  • event.pageX event.pageY 获取事件发生时,鼠标相对文档的偏移值。

  • event.offsetX event.offsetY 获取事件发生时鼠标相对触发事件的元素的偏移值。

  • var code = e.charCode || e.keyCode || e.which; 取按键字符的编码。

  • event.ctrlKey event.altKey event.shiftKey 返回布尔值,事件发生时,对应的功能键是否被按下。

return false 即阻止事件传递又阻止与事件关联的默认动作的执行

事件的执行机制

事件的执行机制包含捕获和冒泡两种,事件触发时总是先进行捕获后进行冒泡。

  • 事件捕获阶段

    当事件触发时,先从根节点开始向触发事件的元素方向,依次触发相同的事件。

  • 事件冒泡阶段

    当事件触发且捕获阶段结束后,由触发事件的元素向根元素方向,依次触发相同的事件。

假设有如下dom结构:

  <div id="a">
    <div id="b">
      <div id="c"></div>
    </div>
  </div>

我们分别为a、b、c元素附加事件:

DOM0的事件是冒泡方式,无法修改。所以点击c时,触发顺序是c、b、a

DOM2的事件可以指定方式,addEventListener(事件名称,处理函数,运行模式):

    aa.addEventListener('click', function () {
      log.innerHTML += 'aa,'
    }, true)//true -->捕获,false-->冒泡

当以捕获方式运行时,点击c时,触发顺序是a、b、c。

使用e.stopPropagation();可以阻止传递的过程,

注意:传递的过程是先捕获后冒泡。

事件委托

当我们不确定元素的数量和内容时,无法预先为元素附加事件,这个时候,我们可以将事件附加到一个确定存在的祖先元素之上,这个方法就叫事件的委托。可以为未来存在的元素预先设置事件。

    ul.onclick = function (e) {
      if (e.target.tagName == 'LI') {
        alert(e.target.innerText)
      }
    }

为ul元素附加事件,未来的li也会触发。

使用e.target获得当前触发事件的元素,判断是li元素后可以做后续操作。

也可以使用e.currentTarget来获取真实附加事件的元素。

事件的触发

事件可以由js来触发。例如:点击事件:

元素.click() 是真实触发点击事件。

元素.onclick() 不真实触发点击事件,只是事件附加的处理函数。

所有事件都是如此。

低级事件和高级事件

低级事件:无条件触发,例如:鼠标按下、按键按下

高级事件:有条件触发,例如:单击、双击、

鼠标事件

鼠标事件

  • click 单击

  • dblclick 双击

  • contextmenu 右键

  • mouseMove 鼠标移动

  • mouseenter 鼠标移入(不能由子孙节点触发)

  • mouseover 鼠标移入

  • mouseleave 鼠标移出(不能由子孙节点触发)

  • mouseout 鼠标移出

  • mouseDown 鼠标按键按下

  • mouseUp 鼠标按键弹起

  • onwheel 滚轮事件

键盘事件

  • keydown

  • keypress

  • keyup

按键触发顺序是keydown->keypress->keyup,对于没有字符输出的按键,不会触发keypress。

字符是在keypress事件正常完结后输入。

要阻止字符输入,可以选择keydown、keypress,建议使用keypress。

要统计字数,可以使用keyup、input。

   var code = e.charCode || e.keyCode || e.which;

获取按键编码存在一定的兼容性问题,因此做如上处理。

表单事件

  • submit 表单提交事件。它只能在form元素上起作用。

  • reset 表单重置事件。它只能在form元素上起作用。

  • change 表单元素提交值发生改变时。经常用在单选、复选、下拉菜单、文件域。它可以用在所有表单元素之上,如果用在文本域之上,触发条件是,当元素获得焦点时,事件存储一次当前值,直到它失去焦点时再次获取一次当前值和之前的作比较,不同才会触发,它的触发不够及时,但是,在特定条件下是可以使用的。

  • input 当用户在文本、密码等可输入的表单元素内输入时触发。

  • select 当用户选择文本、密码等可输入的表单元素内的字符时触发。

  • 焦点

    • focus blur 没有冒泡

    • focusin focusout 有冒泡

其他事件

   //禁止选择
    document.documentElement.onselectstart = function () {
      return false;
    }
    //进制右键菜单
    document.documentElement.oncontextmenu = function () {
      return false;
    }
    //禁止复制
    document.documentElement.oncopy = function () {
      return false;
    }
​
    //禁止剪切
    document.documentElement.oncut = function () {
      return false;
    }
​
    //禁止粘贴
    document.documentElement.onpaste = function () {
      return false;
    }

表单本地验证

单选

可以直接使用value属性来获取选中项的值:

    form.gender.value //如果没有选中,则返回空字符串,否则返回选中项的值

单选一般只做表单提交验证,不做提交前验证:

    form.onsubmit = function(e){
        let key = true;
        
        if(!form.gender.value){
            key = false;
        }
        
        if(!key){
            e.preventDefault();
        }
    }

复选

也是只做表单提交时的验证:

    form.onsubmit = function(e){
        let key = true;
        
        let n = 0;
        for(let i=0;i<form.hobby.length;i++){
            if(form.hobby[i].checked){
                n++;
            }
        }
        if(n<1 || n>4){//要求复选至少选中一个,最多选中4个
            key = false;
        }
        
        if(!key){
            e.preventDefault();
        }
    }

也可以做提交前验证:

        for(let i=0;i<form.hobby.length;i++){
            form.hobby[i].onchange = hobby_change;
        }
​
        function hobby_change(){
            let n = 0;
            for(let i=0;i<form.hobby.length;i++){
                if(form.hobby[i].checked){
                    n++;
                }
            }
            if(n<1){
                this.checked = true;
            }
            if(n>3){
                this.checked = false;
            }
        }

Regexp

正则表达式:描述字符在字符串中的正向排列规律的表达式。

建立:

    const reg = new Regexp('abc','ig');
          reg = /abc/ig;

包含表达式内容及运行模式。

  • 运行模式 :

    i:忽略大小写

    g:全文匹配

    m:多行匹配

  • 规则:

    • \ 转义字符,在字符串和正则中都有特殊含义,想要匹配普通的字符\需要输入\\

    • /^ $/ 匹配字符串的开始、结尾

    • [abc] [a-z0-9_] [\u0100-\uffff] 中括号内的任意一个字符

    • [^abc] 除了中括号内的字符之外的任意一个字符

    • (abc|edc|ac) 表示abc或者edc或者ac之中的任意一组字符

    • /[\u4e00-\u9fa5\uf900-\ufa2d]/ 匹配中文

    • 元字符:

      .查找单个字符,除了换行和行结束符。
      \w查找数字、字母及下划线。
      \W查找非单词字符。
      \d查找数字。
      \D查找非数字字符。
      \s查找空白字符。
      \S查找非空白字符。
      \b匹配单词边界。
      \B匹配非单词边界。
  • 量词:

    {x,y} 最少x次,最多y次

    {x,} 最少x次

    {x} 精确的出现x次

    + {1,}

    * {0,}

    ? {0,1}

    方法:

    正则的方法:

    test(字符串)  返回布尔值。
    ​
    exec(字符串)  返回匹配到的字符串及出现的位置。

    字符串:

string.split()
​string.search()​
string.replace()​
string.match()  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值