• javascript基础-(2)


    一、DOM介绍

    1、什么是DOM

      DOM(Document Object Model):文档对象模型,DOM 为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构。目的其实就是为了能让js操作html元素而制定的一个规范。

      DOM就是由节点组成的。

    2、解析过程

      HTML加载完毕,渲染引擎会在内存中把HTML文档,生成一个DOM树,getElementById是获取内中DOM上的元素节点。然后操作的时候修改的是该元素的属性

    3、DOM树(一切都是节点)

      DOM的数据结构如下:

      

       上图可知,在HTML当中,一切都是节点:(非常重要)

        - 元素节点:HMTL标签;

        - 文本节点:标签中的文字(比如标签之间的空格、换行);

        - 属性节点::标签的属性;

      整个html文档就是一个文档节点。所有的节点都是Object

      当浏览器载入 HTML 文档, 它就会成为 Document 对象。

        Document 对象是 HTML 文档的根节点。

        Document 对象使我们可以从脚本中对 HTML 页面中的所有元素进行访问。

        提示:

          1)Document 对象是 Window 对象的一部分,可通过 window.document 属性对其进行访问;

          2)通过document.documentElement获取html对象;

          3)通过document.body获取body对象;

    4、DOM可以做什么

      - 找对象(元素节点)

      - 设置元素的属性值

      - 设置元素的样式

      - 动态创建和删除元素

      - 事件的触发响应:事件源、事件、事件的驱动程序

    5、DOM节点的获取

      DOM节点的获取方式其实就是获取事件源的方式

      操作元素节点,必须首先找到该节点。有三种方式可以获取DOM节点:

        // 方式一:通过 id 获取 单个标签
        var oDiv = document.getElementById("box");    
     
        // 方式二:通过 标签名 获得 标签数组,所以有s
        var oArr1 = document.getElementsByTagName("div");  
    
        // 方式三:通过 类名 获得 标签数组,所以有s
        var oArr2 = document.getElementsByClassName("hehe");

      总结:

        1)方式二、三获取的是标签数组,所以习惯性是先遍历之后再使用;

        2)数组中的值即使只有一个,它也是包含在数组里的,想得到这个值要通过索引,例如:

        // 取数组中的第一个元素    
        document.getElementsByTagName("div")[0]; 
    
        // 取数组中的第一个元素    
        document.getElementsByClassName("hehe")[0]; 

    6、DOM访问关系的获取(节点的访问关系,是以属性的方式存在的。)

      DOM的节点并不是孤立的,因此可以通过DOM节点之间的相对关系对它们进行访问。如下:

      

    父节点

    兄弟节点

    单个子节点

    所有子节点

    parentNode

    nextSibling

    firstChild

    childNodes

    nextElementSibling

    firstElementChild

    children

    previousSibling

    lastChild

    previousElementSibling

    lastElementChild

      (1)获取父节点

        调用者就是节点。一个节点只有一个父节点,调用方式就是:

         节点.parentNode

      (2)获取兄弟节点

        a、下一个节点

          ① nextSibling:

            - 火狐、谷歌、IE9+版本:都指的是下一个节点(包括标签、空文档和换行节点)。

            - IE678版本:指下一个元素节点(标签)。

          ② nextElementSibling:

            - 火狐、谷歌、IE9+版本:都指的是前一个元素节点(标签)。

          总结:为了获取前一个元素节点,我们可以这样做:在IE678中用previousSibling,在火狐谷歌IE9+以后用previousElementSibling,于是,综合这两个属性,可以这样写:

             前一个兄弟节点 = 节点.previousElementSibling || 节点.previousSibling

        b、上一个节点

          ① previousSibling:

            - 火狐、谷歌、IE9+版本:都指的是前一个节点(包括标签、空文档和换行节点)。

            - IE678版本:指前一个元素节点(标签)。

          ② previousElementSibling:

            - 火狐、谷歌、IE9+版本:都指的是前一个元素节点(标签)。

          总结:为了获取前一个元素节点,我们可以这样做:在IE678中用previousSibling,在火狐谷歌IE9+以后用previousElementSibling,于是,综合这两个属性,可以这样写:

             前一个兄弟节点 = 节点.previousElementSibling || 节点.previousSibling

        c、补充:获得任意一个兄弟节点:

         节点自己.parentNode.children[index];   // 通过索引得到任意兄弟节点

      (3)获取子节点

        a、第一个节点 | 第一个一个子元素节点:

          ① firstChild:

            - 火狐、谷歌、IE9+版本:都指的是第一个子节点(包括标签、空文档和换行节点)。

            - IE678版本:指第一个子元素节点(标签)。

          ② firstElementChild:

            - 火狐、谷歌、IE9+版本:都指的是第一个子元素节点(标签)。

          总结:为了获取第一个子元素节点,我们可以这样做:在IE678中用firstChild,在火狐谷歌IE9+以后用firstElementChild,于是,综合这两个属性,可以这样写:

             第一个子元素节点 = 节点.firstElementChild || 节点.firstChild 

        b、最后一个子节点 | 最后一个子元素节点:

          ① lastChild:

            - 火狐、谷歌、IE9+版本:都指的是最后一个子节点(包括标签、空文档和换行节点)。

            - IE678版本:指最后一个子元素节点(标签)。

          ② lastElementChild:

            - 火狐、谷歌、IE9+版本:都指的是最后一个子元素节点(标签)。

          总结:为了获取最后一个子元素节点,我们可以这样做:在IE678中用lastChild,在火狐谷歌IE9+以后用lastElementChild,于是,综合这两个属性,可以这样写:

             最后一个子元素节点 = 节点.lastElementChild || 节点.lastChild

        c、获取所有的子节点

          ① childNodes:标准属性。返回的是指定元素的子节点的集合(包括元素节点、所有属性、文本节点)。是W3C的亲儿子。

            - 火狐 谷歌等高本版会把换行也看做是子节点。(了解)

          用法:

              子节点数组 = 父节点.childNodes;   //获取所有节点。

          ② children:非标准属性。返回的是指定元素的子元素节点的集合。【重要】

            - 它只返回HTML节点,甚至不返回文本节点。

            - 在IE6/7/8中包含注释节点(在IE678中,注释节点不要写在里面)。

          虽然不是标准的DOM属性,但它和innerHTML方法一样,得到了几乎所有浏览器的支持。

      (4)nodeType   

        这里讲一下nodeType。

        用法:

            // 获得 body 元素的节点类型:
            console.log(document.body.nodeType); // 1

          - nodeType == 1 表示的是元素节点(标签) 。记住:元素就是标签。

          - nodeType == 2 表示是属性节点 了解

          - nodeType == 3 是文本节点 了解

    7、DOM节点操作  

      上一段的内容:节点的访问关系都是属性

      这一段内容:节点的操作都是函数(方法)

      (1)创建节点(标签节点和文本节点)

          语法:创建的标签节点对象 = document.createElement("标签名"); 

             创建的文本节点对象 = document.createTextNode(“文本内容”);  

        例如

        <script type="text/javascript">
            var oA1 = document.createElement("li");   // 创建一个li标签节点
            var oA2 = document.createElement("abc");   // 也可以创建一个自定义的标签
            var oTxt = document.createTextNode("文本节点");  // 创建一个文本节点
    
            console.log(oA1);  // <li></li>
            console.log(oA2);  // <abc></abc>
            console.log(oTxt);  // "文本节点"
            console.log(typeof oA1,typeof oA2,typeof oTxt);  // object object object
        </script>

      (2)插入节点

        插入节点有两种方式,它们的含义是不同的

        方式一:父节点.appendChild(新的子节点);  例如:

            <div class="parent">
                <div class="da"></div>
                <div class="er"></div>
                <div class="san"></div>
            </div>
        
            <script type="text/javascript">
                setTimeout(function () {
                    var oPar = document.getElementsByClassName('parent')[0];
                    var oP = document.createElement("p");
                    var oTxt = document.createTextNode('文本节点');
        
                    oP.appendChild(oTxt);  // 为p标签添加文本内容
                    oPar.appendChild(oP);  // oPar节点的最后添加新的子节点oP
                },5000)
            </script>

          总结:表示父节点的最后插入一个新的子节点。

        方式二:父节点.insertBefore(新子节点,参考的子节点);   例如:

            <div class="parent">
                <div class="da"></div>
                <div class="er"></div>
                <div class="san"></div>
            </div>
    
            <script type="text/javascript">
                setTimeout(function () {
                    var oPar = document.getElementsByClassName('parent')[0];
                    var oDa = document.getElementsByClassName('da')[0];
                    var oP = document.createElement("p");
                    var oTxt = document.createTextNode('文本节点');
                    oP.appendChild(oTxt);  // 为p标签添加文本内容
    
                    oPar.insertBefore(oP,oDa);  // 在oDa节点前添加oPar的子节点oP
                },5000)
            </script>

          总结:此方法有两个参数,第二个参数是参考节点,若参考节点为null,则将在最后插入。

      (3)删除节点

        语法:父节点.removeChild(子节点);  例如:

            <div class="parent">
                <div class="da"></div>
                <div class="er"></div>
                <div class="san"></div>
            </div>
    
            <script type="text/javascript">
                setTimeout(function () {
                    var oPar = document.getElementsByClassName('parent')[0];
                    var oDa = document.getElementsByClassName('da')[0];
                    oPar.removeChild(oDa);
                },5000)
            </script>

        删除自己本身这个节点写法:node1.parentNode.removeChild(node1);

            <div class="parent">
                <div class="da"></div>
                <div class="er"></div>
                <div class="san"></div>
            </div>
    
            <script type="text/javascript">
                setTimeout(function () {
                    var oPar = document.getElementsByClassName('parent')[0];
                    oPar.parentNode.removeChild(oPar);
                },5000)
            </script>

      (4)复制节点(克隆节点)

        语法:要复制的节点.cloneNode();   // 默认参数是false

              要复制的节点.cloneNode(true); 

        例如:

            <div id="myList">
                <div class="A"></div>
                <div class="B">mikl</div>
            </div>
    
            <script>
                var oItm = document.getElementById("myList").lastChild;
                var oCln = oItm.cloneNode(true);
                var oCln2 = oItm.cloneNode();
                console.log(oCln);  // <li>Milk</li>(实际上克隆的是打印不出来的)
                console.log(oCln2); // <li></li>
            </script>

        总结:不带参数/带参数false,表示只复制节点本身,不复制子节点;

                              带参数true,表示既复制节点本身,也复制其所有的子节点;

    8、DOM节点对象属性的获取和赋值

      a、对标签样式的操作,例如:

      对象.style.marginLeft = “20px”;  // 样式驼峰表示

      b、对标签属性的操作,例如:

        对象.src = “1.jpg”; // 直接.属性名
        对象.className = “active”;  // className特殊记,获取类名不是class

      c、对值的操作,例如:

         1)innerText 获取或设置文本,例如:

            对象.innerText = “文本”;

        2)innerHTML 获取或设置文本和标签(能解析标签),例如:

            对象.innerHTML = “<h3>文本</h3>”;

        3)value 一般用于单闭合标签,比如表单元素input输入框,例如:

            对象.value = “alex”;

      d、上面是通过“点语法”获取,通过“=”赋值,也可通过下面方法获取和赋值,例如:

        获取:对象.[“属性名”](className特殊)   或者   对象.getAttribute(“属性名”);

        赋值:对象. setAttribute(“属性名”,”属性值”);

        <body>
            <img src="./images/购物车-hover.png" class="img-box" title="美女图片" alt="地铁一瞥" id="a1">
        
            <script type="text/javascript">
                var myNode = document.getElementsByTagName("img")[0];
            
                console.log(myNode["title"]);  // 美女图片
                console.log(myNode["className"]); // img-box, 注意, 是className
                console.log(myNode.getAttribute("title"));  // 美女图片
                console.log(myNode.getAttribute("class"));   // img-box, 注意, 是class
                myNode.setAttribute("title","美景图片");
                myNode.setAttribute("alt","桂林山水");
            </script> 
        </body>

      e、删除节点的属性

        格式:对象.removeAttribute(“属性名”);

        用法:

            myNode.removeAttribute("class");

    二、关于DOM的事件操作

    1、JavaScript的组成

      JavaScript基础分为三个部分:

        - ECMAScript:JavaScript的语法标准。包括变量、表达式、运算符、函数、if语句、for语句等。

        - DOM:文档对象模型,操作网页上的元素的API。比如让盒子移动、变色、轮播图等。

        - BOM:浏览器对象模型,操作浏览器部分功能的API。比如让浏览器自动滚动。

    2、事件

      JS是以事件驱动为核心的一门语言。

      事件的三要素:事件源,事件,事件驱动程序。

        事件源:引发后续事件的html标签;

                  事件:js中已经定义好了;

                  事件驱动程序:对样式和html的操作,也就是DOM;

      代码书写步骤:(重要)

                  (1)获取事件源:document.getElementById(“box”);

                  (2)绑定事件:事件源box.事件onclick = function(){ 事件驱动程序 };

                  (3)书写事件驱动程序:关于DOM的操作;

      代码示例:

      <body>
      <div id="box">box</div>
    
      <script type="text/javascript">
          // 1、获取事件源
          var div = document.getElementById("box");
          // 2、绑定事件
          div.onclick = function(){
              // 3、书写事件驱动程序
              alert("我是弹出的内容");
          }
      </script>
      </body>

      a、获取事件源的方式(即DOM节点的获取方式)

        // 方式一:通过id获取单个标签元素
        var oDiv = document.getElementById("box");   
    
        // 方式二:通过 标签名 获得 标签数组,所以有s
        var oArr1 = document.getElementsByTagName("div");  
    
        // 方式三:通过 类名 获得 标签数组,所以有s
        var oArr2 = document.getElementsByClassName("hehe");

      

      b、常见事件如下表:

    事件名

    说明

    onclick

    鼠标单击

    ondblclick

    鼠标双击

    onmouseenter

    当鼠标指针移动到元素上时触发,(移到子元素上时不会触发)

    onmouseleave

    当鼠标指针移出元素时触发,(移出子元素时不会触发)

    onmouseover

    鼠标悬停,即鼠标停留在图片等的上方,(移到子元素上时也会触发)

    onmouseout

    鼠标移出,即离开图片等所在的区域,(移出子元素时也会触发)

    onkeydown

    某个键盘按键被按下时触发,键盘事件

    onkeyup

    某个键盘按键被松开时触发,键盘事件

    onload

    网页文档加载事件,框架/对象(Frame/Object)事件

    onunload

    关闭网页时,框架/对象(Frame/Object)事件

    onsubmit

    表单提交事件,表单事件

    onreset

    重置表单时,表单事件

    onchange

    文本内容或下拉菜单中的选项发生改变时触发,表单事件

    onfocus

    获得焦点,表示文本框等获得鼠标光标,表单事件

    onblur

    失去焦点,表示文本框等失去鼠标光标,表单事件

      c、绑定事件的方式

        方式一:直接绑定匿名函数,例如:

        <div id="box" >box</div>
    
        <script type="text/javascript">
            var oDiv = document.getElementById("box");
            oDiv.onclick = function(){
            alert("我是弹出的内容");
            }
        </script>

        方式二:先单独定义函数,再绑定,例如:

      <div id="box" >box</div>
    
      <script type="text/javascript">
          var oDiv = document.getElementById("box");
          oDiv.onclick = fn;   // 注意,这里是fn,不是fn()
          function fn(){
              alert("我是弹出的内容");
          }
      </script>

        方式三:行内绑定,例如:

      <div id="box" onclick="fn()">box</div>  // 注意,这里是fn()
    
      <script type="text/javascript">
          function fn(){
              alert("我是弹出的内容");
          }
      </script>

      d、事件驱动程序

        我们在上面是拿alert举例,不仅如此,我们还可以操作标签的属性和样式。举例如下:

    <body>
        <div id="box" style=" 100px; height: 100px; background-color: pink;"></div>
    
      <script type="text/javascript">
      var oDiv = document.getElementById("box");
      // 点击box时,原本粉色的div变大了,背景变成了红色
      oDiv.onclick = function () {
          oDiv.style.width = "200px";   // 属性值要写引号
          oDiv.style.height = "200px";
          oDiv.style.backgroundColor = "red";
          // 属性名是backgroundColor,不是background-color
      }
      </script>
    </body>  

        注意事项:

                         1)在js里写属性值时,要用引号;

                         2)在js里写属性名时,是驼峰写法,比如backgroundColor,而不是css里面的background-color,记得所有像css属性的text-*、line-*、background-* 等在js中都写成驼峰;

    3、控制元素显示和隐藏有三种方法,如下:

           a、控制style.display属性显示隐藏;

           b、控制className对元素显示隐藏;

           c、对元素的创建和销毁;

           总结:

        1)前两个的特点:初始化的时候有渲染,网页中频繁性的切换建议使用这种;

        2)第三个特点:有生命周期,网页中少量的切换建议使用这种;

    4、onload事件

      a、当页面加载(文本和图片)完毕的时候,触发onload事件,例如:

      <script type="text/javascript">
          window.onload = function(){
              console.log("小马哥");  // 页面(文档和图片)加载完毕时,执行
          }
      </script>

        问题:有一点我们要知道:js的加载是和html同步(按顺序)加载的,因此,如果使用元素在定义元素之前,容易报错。

        解决方案:这个时候,onload事件就能派上用场了,我们可以把使用元素的代码放在onload里,就能保证这段代码是最后执行。所以建议:整个页面上所有元素加载完毕再执行js内容。所以,window.onload可以解决使用标签在定义标签之前的问腿。

      b、如果遇到网络不稳定,图片没有加载完成,则还是不会执行js代码,所以我们可以写成当文档加载完再执行js代码,写法如下:

      <script type="text/javascript">
          document.onload = function(){
             console.log("小马哥");  // 文档加载完毕时,打印字符串
          }
      </script>

        注意:这两种都有事件覆盖现象,也就是只能写一个,写多个会被最后一个覆盖。

  • 相关阅读:
    结对作业
    读《构建之法》第四章、第十七章
    2016012060+小学四则运算练习软件项目报告
    《构建之法》第1、2、16章阅读随笔
    我与软件
    2016012039+张琪+散列函数的应用及其安全性
    结对作业
    读《构建之法》第四、十七章有感
    2016012039 + 小学四则运算练习软件项目报告
    读书笔记(第1、2、16章)
  • 原文地址:https://www.cnblogs.com/kangqi452/p/12029337.html
Copyright © 2020-2023  润新知