08-JS基础-DOM相关

  • 简介
    Document Object Model 文档对象模型,通过DOM可以来任意来修改网页中各个内容。
    文档指的是网页,一个网页就是一个文档。
    对象指将网页中的每一个节点都转换为对象。
    模型用来表示节点和节点之间的关系,方便操作页面。
  • 节点(Node)
    节点是构成网页的最基本的单元,网页中的每一个部分都可以称为是一个节点。
    虽然都是节点,但是节点的类型却是不同的,常用的节点:
    - 文档节点 (Document),代表整个网页
    - 元素节点(Element),代表网页中的标签
    - 属性节点(Attribute),代表标签中的属性
    - 文本节点(Text),代表网页中的文本内容
DOM操作

在网页中浏览器已经为我们提供了document对象,它代表的是整个网页,它是window对象的属性,可以在页面中直接使用。

document查询方法:
1)根据元素的 id 属性查询一个元素节点对象:
  document.getElementById("id属性值");
2)根据元素的name属性值查询一组元素节点对象:
  document.getElementsByName("name属性值");
3)根据标签名来查询一组元素节点对象:
  document.getElementsByTagName("标签名");

元素的属性:

读取元素的属性:
语法:元素.属性名

修改元素的属性:
语法:元素.属性名 = 属性值

innerHTML
使用该属性可以获取或设置元素内部的HTML代码

city. innerHTML += "
  • 广州
  • ";
    • 文档的加载
      浏览器在加载一个页面时,是按照自上向下的顺序加载的,加载一行执行一行。
      如果将js代码编写到页面的上边,当代码执行时,页面中的DOM对象还没有加载,此时将会无法正常获取到DOM对象,导致DOM操作失败。
      解决方式一:
      可以将js代码编写到body的下边
    
        
        
    
    

    解决方式二:
    将js代码编写到window.onload = function(){}中,
    window.onload 对应的回调函数会在整个页面加载完毕以后才执行。

    
    
    • DOM查询
    1. 通过具体的元素节点来查询

    通过标签名查询当前元素的指定后代元素
    元素.getElementsByTagName()

    获取当前元素的所有子节点, 会获取到空白的文本子节点,根据DOM标准,标签间空白也会当成文本子节点。
    元素.childNodes

    获取当前元素的所有子元素
    元素.children

    获取当前元素的第一个子节点
    元素.firstChild

    获取当前元素的最后一个子节点
    元素.lastChild

    获取当前元素的父元素
    元素.parentNode

    获取当前元素的前一个兄弟节点
    元素.previousSibling

    获取当前元素的后一个兄弟节点
    元素.nextSibling

    1. innerHTML和innerText
      这两个属性并没有在DOM标准定义,但是大部分浏览器都支持这两个属性。
      两个属性作用类似,都可以获取到标签内部的内容,
      不同是innerHTML会获取到html标签,而innerText会自动去除标签。
      如果使用这两个属性来设置标签内部的内容时,没有任何区别的。

    读取标签内部的文本内容
    元素.firstChild.nodeValue

    • document对象的其他的属性和方法

    document.all
    获取页面中的所有元素,相当于document.getElementsByTagName("*");

    document.documentElement
    获取页面中html根元素

    document.body
    获取页面中的body元素,body的引用

    document.getElementsByClassName()
    根据元素的class属性值查询一组元素节点对象(这个方法不支持IE8及以下的浏览器)

    document.querySelector()
    根据CSS选择器去页面中查询一个元素
    如果匹配到的元素有多个,则它会返回查询到的第一个元素

    document.querySelectorAll()
    根据CSS选择器去页面中查询一组元素
    会将匹配到所有元素封装到一个数组中返回,即使只匹配到一个

    • DOM增删改

    根据标签名创建一个元素节点对象
    document.createElement()

    根据文本内容创建一个文本节点对象
    document.createTextNode()

    向父节点中添加指定的子节点
    父节点.appendChild(子节点)

    // 向父节点city中添加子节点li
    //方式一
    var li = document.createElement("li");
    var text = document.createTextNode("广州");
    li.appendChild(text);
    city.appendChild(li);
    
    // 方式二
    city. innerHTML += "
  • 广州
  • "; // 方式三(推荐) var li = document.createElement("li"); li.innerHTML = "广州"; city.appendChild(li);

    将一个新的节点插入到旧节点的前边
    父节点.insertBefore(新节点,旧节点)

    使用一个新的节点去替换旧节点
    父节点.replaceChild(新节点,旧节点)

    删除指定的子节点
    父节点.removeChild(子节点)
    推荐方式:子节点.parentNode.removeChild(子节点)

    • DOM对CSS的操作
    1. 读取和修改内联样式
      使用style属性来操作元素的内联样式
    • 读取内联样式:
      语法:元素.style.样式名
    元素.style.width
    元素.style.height
    

    注意:如果样式名中带有-,则需要将样式名修改为驼峰命名法
    将-去掉,然后-后的字母改大写, 比如:background-color --> backgroundColor , border-width ---> borderWidth

    • 修改内联样式:
      语法:元素.style.样式名 = 样式值

    通过style修改的样式都是内联样式,由于内联样式的优先级比较高,所以我们通过JS来修改的样式,往往会立即生效,但是如果样式中设置了!important,则内联样式将不会生效。

    • 读取元素的当前样式
      - 正常浏览器
      使用getComputedStyle()
      这个方法是window对象的方法,可以返回一个对象,这个对象中保存着当前元素生效样式。
      参数:
      要获取样式的元素
      可以传递一个伪元素,一般传null
    // 获取元素的宽度
    getComputedStyle(box , null)["width"];
    

    通过该方法读取到样式都是只读的不能修改

    // IE8 使用currentStyle
    // 元素.currentStyle.样式名
    box.currentStyle["width"]
    
    • 其他的样式相关的属性
      以下样式都是只读的

    clientHeight
    元素的可见高度,指元素的内容区和内边距的高度

    clientWidth
    元素的可见宽度,指元素的内容区和内边距的宽度

    offsetHeight
    整个元素的高度,包括内容区、内边距、边框

    offfsetWidth
    整个元素的宽度,包括内容区、内边距、边框

    offsetParent
    当前元素的定位父元素
    离他最近的开启了定位的祖先元素,如果所有的元素都没有开启定位,则返回body

    offsetLeft、offsetTop
    当前元素和定位父元素之间的偏移量
    offsetLeft 水平偏移量
    offsetTop 垂直偏移量

    scrollHeight、scrollWidth
    获取元素滚动区域的高度和宽度

    scrollTop、scrollLeft
    获取元素垂直和水平滚动条滚动的距离
    判断滚动条是否滚动到底
    垂直滚动条: scrollHeight - scrollTop = clientHeight
    水平滚动条: scrollWidth - scrollLeft = clientWidth

    DOM其它操作
    • DOM操作CSS
      通过JS修改元素的样式:

    语法:元素.style.样式名 = 样式值

    注:如果CSS的样式名中含有-,这种名称在JS中是不合法的比如background-color,需要将这种样式名修改为驼峰命名法backgroundColor。
    我们通过style属性设置的样式都是内联样式,而内联样式有较高的优先级,所以通过JS修改的样式往往会立即显示。
    但是如果在样式中写了!important,则此时样式会有最高的优先级,即使通过JS也不能覆盖该样式,此时将会导致JS修改样式失效,所以尽量不要为样式添加 !important。

    读取元素的样式:

    语法:元素.style.样式名

    注:通过style属性设置和读取的都是内联样式,无法读取样式表中的样式。

    window.onload = function(){             
        /*
        * 点击按钮以后,修改box1的大小
        */
        //获取box1
        var box1 = document.getElementById("box1");
        var btn01 = document.getElementById("btn01");
        btn01.onclick = function(){
                        
            box1.style.width = "300px";
            box1.style.height = "300px";
            box1.style.backgroundColor = "yellow";
        };
                    
        //点击按钮2以后,读取元素的样式
        var btn02 = document.getElementById("btn02");
        btn02.onclick = function(){
        
            alert(box1.style.width);   
            getStyle(box1 , "width");
        };
    
        /*
        * 定义一个函数,用来获取指定元素的当前的样式
        * 参数:
        *       obj 要获取样式的元素
        *       name 要获取的样式名
        */
        function getStyle(obj , name){
                    
            if(window.getComputedStyle){
                //正常浏览器的方式,具有getComputedStyle()方法
                return getComputedStyle(obj , null)[name];
            }else{
                //IE8的方式,没有getComputedStyle()方法
                return obj.currentStyle[name];
            }
            //return window.getComputedStyle?getComputedStyle(obj , null)[name]:obj.currentStyle[name];
        }
    };
    
    • 获取其它css操作的属性:
    /*
    * clientWidth
    * clientHeight
    * 这两个属性可以获取元素的可见宽度和高度
    * 这些属性都是不带px的,返回都是一个数字,可以直接进行计算
    * 会获取元素宽度和高度,包括内容区和内边距
    * 这些属性都是只读的,不能修改
    */
    box1.clientWidth;
    box1.clientHeight;
    
    /*
    * offsetWidth
    * offsetHeight
    * 获取元素的整个的宽度和高度,包括内容区、内边距和边框
    */
    box1.offsetWidth;
                        
    /*
    * offsetParent
    * 可以用来获取当前元素的定位父元素,会获取到离当前元素最近的开启了定位的祖先元素
    * 如果所有的祖先元素都没有开启定位,则返回body
    */
    var op = box1.offsetParent;
    
    /*
    * offsetLeft
    * 当前元素相对于其定位父元素的水平偏移量
    * offsetTop
    * 当前元素相对于其定位父元素的垂直偏移量
    */
    box1.offsetLeft;
                        
    /*
    * scrollWidth
    * scrollHeight
    * 可以获取元素整个滚动区域的宽度和高度
    */
    box4.clientHeight;
    box4.scrollWidth;
                        
    /*
    * scrollLeft
    * 可以获取水平滚动条滚动的距离
    * scrollTop
    * 可以获取垂直滚动条滚动的距离
    */
    box4.scrollLeft;
    box4.scrollTop;                 
    //当满足scrollHeight - scrollTop == clientHeight,说明垂直滚动条滚动到底了
    //当满足scrollWidth - scrollLeft == clientWidth,说明水平滚动条滚动到底
    
    事件(Event)

    事件指的是用户和浏览器之间的交互行为。比如:点击按钮、关闭窗口、鼠标移动 ... ...
    可以为事件来绑定回调函数来响应事件。
    绑定事件的方式:
    1.可以在标签的事件属性中设置相应的JS代码

    
    

    2.可以通过为对象的指定事件属性设置回调函数的形式来处理事件

    
    
    
    • 事件对象
      当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进响应函数,在事件对象中封装了当前事件相关的一切信息,比如:鼠标的坐标、键盘哪个按键被按下、鼠标滚轮滚动的方向等。
      可以在响应函数中定义一个形参,来使用事件对象,但是在IE8以下浏览器中事件对象没有做为实参传递,而是作为window对象的属性保存。
    元素.事件 = function(event){
        event = event || window.event;
    };
                
    元素.事件 = function(e){
        e = e || event;
    };
    
    // 当鼠标在areaDiv中移动时,在showMsg中来显示鼠标的坐标
    window.onload = function(){
        //获取两个div
        var areaDiv = document.getElementById("areaDiv");
        var showMsg = document.getElementById("showMsg");
        /*
         * onmousemove
         * 该事件将会在鼠标在元素中移动时被触发
         *
         */
         areaDiv.onmousemove = function(event){
             // IE8以下浏览器中事件对象作为window对象的属性保存。
             // 解决事件对象的兼容性问题。
             event = event || window.event;
            /*
             * clientX可以获取鼠标指针的水平坐标
             * cilentY可以获取鼠标指针的垂直坐标
             */
            var x = event.clientX;
            var y = event.clientY;
            //在showMsg中显示鼠标的坐标
            showMsg.innerHTML = "x = "+x + " , y = "+y;
         };
    };
    
    • 事件的冒泡(Bubble)
      事件的冒泡指的是事件向上传导,当后代元素上的事件被触发时,将会导致其祖先元素上的同类事件也会触发。
      事件的冒泡大部分情况下都是有益的,如果需要取消冒泡,则需要使用事件对象来取消。
      可以将事件对象的cancelBubble设置为true,即可取消冒泡
    元素.事件 = function(event){
        event = event || window.event;
        event.cancelBubble = true;
    };
    
    • 事件的委派
      将事件统一绑定给元素共同的祖先元素,当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理。
      事件的委派利用冒泡,减少了事件绑定的次数,提高程序性能。

    • 事件的绑定
      使用 对象.事件 = 函数 的形式绑定响应函数,只能同时为一个元素的一个事件绑定一个响应函数。如果绑定多个,先绑定的会被覆盖。

    1. addEventListener()
      通过addEventListener()方法也可以为元素绑定响应函数,可以同时为一个元素的相同事件同时绑定多个响应函数,当事件被触发时,响应函数将会按照函数的绑定顺序执行。
      注:不支持IE8及以下的浏览器

    参数:
    1.事件的字符串,不要on
    2.回调函数,当事件触发时该函数会被调用
    3.是否在捕获阶段触发事件,需要一个布尔值,一般都传false

    var btn2 = document.getElementById("btn2");
    btn2.addEventListener("click",function(){
        alert(1);
    },false);
    
    btn2.addEventListener("click",function(){
        alert(2);
    },false);
    
    1. attachEvent()
      在IE8中可以使用attachEvent()来绑定事件,可以同时为一个事件绑定多个处理函数,但是它是后绑定先执行,执行顺序和addEventListener()相反。

    参数:
    1.事件的字符串,要on
    2.回调函数

    btn2.attachEvent("onclick",function(){
        alert(1);
    });
                    
    btn2.attachEvent("onclick",function(){
        alert(2);
    });
    

    注:addEventListener()中的this,是绑定事件的对象
      attachEvent()中的this,是window

    //定义一个函数,用来为指定元素绑定响应函数
    /*
     * 参数:
     *  obj 要绑定事件的对象
     *  eventStr 事件的字符串(不要on)
     *  callback 回调函数
     */
     function bind(obj , eventStr , callback){
        if(obj.addEventListener){
            //大部分浏览器兼容的方式
            obj.addEventListener(eventStr , callback , false);
        }else{
            /*
             * this是谁由调用方式决定
             * callback.call(obj)
             */
            //IE8及以下
            obj.attachEvent("on" + eventStr , function(){
                //在匿名函数中调用回调函数
                callback.call(obj);
            });
        }
    }
    
    • 事件的传播
      事件传播分成了三个阶段
    1. 捕获阶段
      在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件;
    2. 目标阶段
      事件捕获到目标元素,捕获结束开始在目标元素上触发事件;
    3. 冒泡阶段
      事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件;
      如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true。
      一般情况下我们不会希望在捕获阶段触发事件,所以这个参数一般都是false。
      注:IE8及以下的浏览器中没有捕获阶段
    • 拖拽
      拖拽的流程
      1. 当鼠标在被拖拽元素上按下时,开始拖拽   onmousedown
      2. 当鼠标移动时被拖拽元素跟随鼠标移动    onmousemove
      3. 当鼠标松开时,被拖拽元素固定在当前位置   onmouseup
    var box = document.getElementById("box");
    //为box绑定一个鼠标按下事件
    box.onmousedown = function(event){
        // 设置box捕获所有鼠标按下的事件
        // setCapture() 只有IE支持,但是在火狐中调用时不会报错,而如果使用chrome调用,会报错
        box.setCapture && box.setCapture();
    
        event = event || window.event;
        //div的偏移量 鼠标.clentX - 元素.offsetLeft
        //div的偏移量 鼠标.clentY - 元素.offsetTop
        var ol = event.clientX - box1.offsetLeft;
        var ot = event.clientY - box1.offsetTop;
                        
        //为document绑定一个onmousemove事件
        document.onmousemove = function(event){
            event = event || window.event;
            //获取鼠标的坐标
            var left = event.clientX - ol;
            var top = event.clientY - ot;
            //修改box1的位置
            box1.style.left = left+"px";
            box1.style.top = top+"px";
        };
                        
        //为document绑定一个鼠标松开事件
        document.onmouseup = function(){
            //取消document的onmousemove事件
            document.onmousemove = null;
            //取消document的onmouseup事件
            document.onmouseup = null;
            //当鼠标松开时,取消对事件的捕获
            obj.releaseCapture && obj.releaseCapture();
        };
        return false;
    };
    

    当我们拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,此时会导致拖拽功能的异常,这个是浏览器提供的默认行为,如果不希望发生这个行为,则可以通过return false来取消默认行为。但是这招对IE8不起作用

    • 滚轮事件
      onmousewheel 鼠标滚轮滚动事件,会在滚轮滚动时触发,但是火狐不支持该属性。在火狐中需要使用 DOMMouseScroll 来绑定滚动事件,该事件需要通过addEventListener()函数来绑定。
      使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false, 需要使用event来取消默认行为event.preventDefault(); , 但是IE8不支持event.preventDefault();
    window.onload = function(){
        var box1 = document.getElementById("box1");
        //为box绑定一个鼠标滚轮滚动的事件
        box.onmousewheel = function(event){
            event = event || window.event;
            //event.wheelDelta 可以获取鼠标滚轮滚动的方向,wheelDelta这个值不看大小,只看正负
            //alert(event.wheelDelta);
            //wheelDelta这个属性火狐中不支持,在火狐中使用event.detail来获取滚动的方向                   
            /*
             * 当鼠标滚轮向下滚动时,box变长
             *  当滚轮向上滚动时,box变短
             */
            //判断鼠标滚轮滚动的方向
            if(event.wheelDelta > 0 || event.detail < 0){
            //向上滚,box变短
                box.style.height = box1.clientHeight - 10 + "px";
            }else{
                //向下滚,box变长
                box.style.height = box1.clientHeight + 10 + "px";
             }
    
              event.preventDefault && event.preventDefault();
    
              return false;                 
         };
        //为火狐绑定滚轮事件
        bind(box1,"DOMMouseScroll",box1.onmousewheel);
    };
                
    function bind(obj , eventStr , callback){
        if(obj.addEventListener){
            //大部分浏览器兼容的方式
            obj.addEventListener(eventStr , callback , false);
        }else{
            //IE8及以下
            obj.attachEvent("on"+eventStr , function(){
                //在匿名函数中调用回调函数
                callback.call(obj);
            });
        }
    }
    
    • 键盘事件
      onkeydown 按键被按下
      对于onkeydown来说如果一直按着某个按键不松手,则事件会一直触发。当onkeydown连续触发时,第一次和第二次之间会间隔稍微长一点,其他的会非常的快,这种设计是为了防止误操作的发生。
      onkeyup 按键被松开
      键盘事件一般都会绑定给一些可以获取到焦点的对象或者是document。

    可以通过keyCode来获取按键的编码, 通过它可以判断哪个按键被按下。
    除了keyCode,事件对象中还提供了几个属性:altKey、ctrlKey、shiftKey 这三个用来判断alt ctrl 和 shift是否被按下,按下则返回true,否则返回false。

    document.onkeydown = function(event){
        event = event || window.event;
        //console.log(event.keyCode);
                        
        //判断y和ctrl是否同时被按下
        if(event.keyCode === 89 && event.ctrlKey){
            console.log("ctrl和y都被按下了");
        }
    };
    /*document.onkeyup = function(){
        console.log("按键松开了");
    };*/
    

    你可能感兴趣的:(08-JS基础-DOM相关)