JavaScript知识点三(DOM)

目录

前言

Web APIS和JS基础关联性

DOM

获取DOM元素

事件

事件概述

注册事件(绑定事件)

删除事件(解绑事件)

DOM事件流

事件对象

事件委托(代理、委派)

常用的鼠标与键盘事件对象

操作元素

改变元素内容

改变常用元素的属性

改变表单元素的属性

改变元素的样式属性

自定义属性的操作

节点操作

为什么要学习节点操作?

节点概述

节点层级

创建节点 

添加节点

删除节点

复制节点

三种动态创建元素区别

示例


前言

Web APIS和JS基础关联性

    JS为基础阶段:主要学习ECMAScript标准规定的基本语法,但是做不了常用的网页交互效果;
    Web APIs阶段:Web APIs是W3C组织的标准,主要学习DOM和BOM,这部分是js独有的部分,主要是学习页面交互功能,但需要JS基础的课程内容做基础。
            Web APIs是浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM),主要针对浏览器提供的接口,用于做交互效果。
            Web APIs一般都有输入和输出(函数的传参和返回值),Web APIs很多都是方法(函数);
    一句话总结:JS基础学习、ECMAScript基础语法为后面做铺垫,Web APIs是JS的应用,大量使用JS基础语法做交互效果。

DOM

        DOM(Document ObjectModel,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML或XML)的标准编程接口;
          W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式;
  DOM树有如下定义:
  文档:一个页面就是一个文档,DOM中使用document表示;
  元素:页面中的所有标签都是元素,DOM中使用element表示;
  节点:网页中的所有内容都是节点(如标签、属性、文本、注释等),DOM中使用node表示;
  注意:DOM中如上所有内容都看做对象;

获取DOM元素

有四种方式获取DOM元素:根据ID获取、根据标签名获取、通过HTML5新增的方法获取、特殊元素获取。

  • 根据ID获取 

使用getElementById()方法可获取带有ID的元素对象。

<body>
   <div id = 'ids'>今天不上班</div>
</body>
<script>
   var ids = document.getElementById('ids')
   console.log(ids); // <div id = 'ids'>今天不上班</div>
 </script>
  • 根据标签名获取

使用getElementsByTagName()方法可返回带有指定标签名的对象的集合。

返回的是带有指定标签名的对象的集合(伪数组形式);所以操作里面的元素需要遍历;

<body>
  <ul>
     <li>好好学习</li>
     <li>天天向上</li>
     <li>报效祖国</li>
  </ul>
</body>
<script>
  var tag = document.getElementsByTagName('li')
  console.log(tag);
  for (var i = 0; i < tag.length; i++) {
    console.log(tag[i]);
  }
</script>
  • 通过HTML5新增的方法获取

使用document.getElementsByClassName('类名'),根据类名返回元素对象集合(获取的也是伪数组形式);此处方法参数类名中不用加符号.

<body>
   <div class="name">李雷和韩梅梅</div>
</body>
<script>
   var nm = document.getElementsByClassName('name');
   console.log(nm);
</script>

 使用document.querySelector('选择器'),根据指定选择器返回第一个元素对象;querySelector里面的参数要注意选择器需要加符号,如类选择器为.类选择器

<body>
  <div class="name">李雷和韩梅梅</div>
  <div class="name">语文和数学</div>
</body>
<script>
  var nms = document.querySelector('.name');
  console.log(nms); // <div class="name">李雷和韩梅梅</div>
</script>

使用document.querySelectorAll('选择器')返回指定选择器的所有元素对象集合;

<body>
  <div class="name">李雷和韩梅梅</div>
  <div class="name">语文和数学</div>
</body>
<script>
  var nms = document.querySelectorAll('.name'); // 是一个伪数组
  console.log(nms);
</script>
  • 特殊元素(body、html)获取

 获取body元素:document.body(一切都包含在里面,包括空格、注释等);

<body>
  <div class="name">语文和数学</div>
  <script>
  // 获取body元素
     var bodys = document.body;
     console.log(bodys);
  </script>
</body>

获取html元素:document.documentElement;  // html标签内的都会包含在里面;

事件

事件概述

   JavaScript使得有能力创建动态页面,而事件是可以被JavaScript侦测到的行为(触发---响应机制)
   例如:网页中的每个元素都可以产生某些可以触发JavaScript的事件,例如:在用户点击某按钮时产生一个事件,然后去执行某些操作;
事件有三部分组成 事件源 事件类型 事件处理程序,也被称为事件三要素
    事件源:即事件被触发的对象,一般是按钮;
    事件类型:即通过何种方式触发事件,如鼠标经过还是鼠标点击,或是键盘按下;
    事件处理程序:一般是通过函数赋值的方式完成;

<body>
    <!-- 事件源 按钮 -->
    <button id='btn'>点我!</button>
</body>
<script>
    // 事件源 按钮
    var btn = document.getElementById('btn');
    // 事件类型及事件处理
    btn.onclick = function() {
        alert('猜猜我是谁!')
    }
</script>

基于此,执行事件的步骤如下:
    1、获取事件源
    2、注册事件(绑定事件)
    3、添加事件处理程序(采取函数赋值形式);

常见的鼠标事件如下:

鼠标事件  触发条件
onclick          鼠标点击左键触发
onmouseover    鼠标经过触发
onmouseout      鼠标离开触发
onfocus          获得鼠标焦点触发
onblur          失去鼠标焦点触发
onmousemove      鼠标移动触发
onmouseup        鼠标弹起触发
onmousedown    鼠标按下触发

注册事件(绑定事件)

给元素添加事件,称为注册事件或绑定事件;
注册事件有两种方式:传统方式和方法监听注册方式

传统注册方式:
    利用on开头的事件,如onclick、onmouseover等

<body>
    <button>点我</button>
    <script>
        var btn = document.querySelector('button');
        btn.onclick = function() {
            alert("点我干什么~") // 该警示框不会被弹出
        }
        btn.onclick = function() {
            alert("你猜谁会弹出~") // 该警示框会被弹出
        }
    </script>
</body>

    特点:注册事件的唯一性:同一个元素同一事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数(即只能绑定一个函数);

方法监听注册方式:
    该方式是w3c标准的推荐方式,注意:addEventListener()它是一个方法,ie9之前的只支持addEvent()方法;

  • addEventListener()方法

    特点:同一个元素同一个事件可以注册多个监听器,会按注册事件的注册顺序依次执行

eventTarget.addEventListener(type, Listener[, useCapture])

该方法将指定的监听器(监听器即事件处理函数)注册到eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数;
该方法接收三个参数:
      type:事件类型字符串,如click、mouseover等,此处事件类型不要带on!
      listener: 即事件处理函数,当事件发生时,则会调用该监听函数;

      useCapture:是可选参数,用布尔值表示,默认是false,设置为false,则为冒泡阶段,若为true则为捕获阶段;

<body>
    <button>点我</button>
    <button>还是点我吧</button>
    <script>
        var btn = document.querySelectorAll('button');
        btn[1].addEventListener('click', function() {
            alert('我能弹出!') // 该警示框能弹出
        })
        btn[1].addEventListener('click', function() {
            alert('我也能弹出!') // 该警示框也能弹出
        })
    </script>
</body>
  • attachEvent事件监听方式
 eventTarget.attachEvent(eventNameWithOn,callback)

该方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定的事件时,指定的回调函数就会被执行。
该方法接收两个参数:
      eventNameWithOn:事件类型字符串,如onclick、onmouseover,注意:要带上on
      callback:事件处理函数,当目标触发事件时回调函数被调用;

<body>
    <button>试试我</button>
    <script>
        btn[2].attachEvent('onclick', function() {
            alert('在ie9之前搞定~')
        })
    </script>
</body>

兼容性方法:

 function addEventListener(element, eventName, fn) {
       // 判断当前浏览器是否支持addEventListener方法
       if(element.addEventListener) {
        element.addEventListener(eventName, fn);
       } else if (element.attachEvent) {
        element.attachEvent("on" + eventName, fn);
       } else {
        // 相当于 element.onclick = fn
        element['on' + eventName] = fn;
       }
      }

删除事件(解绑事件)

传统注册方式: 

eventTarget.onclick = null;

方法监听注册方式:

eventTarget.removeEventListener(type,listener[, useCapture]); // 方法一
eventTarget.detachEvent(evnetNameWithOn, callback); // 方法二 适用于低版本浏览器

    方法监听注册方式在注册事件时,监听器最好不要设置为匿名函数,否则这里的listener还要写一遍匿名函数,并且函数不用加小括号(),如fn1不写成fn1

<body>
    <button>点我</button>
    <button>还是点我吧</button>
    <button>试试我</button>
    <script>
        var btn = document.querySelectorAll('button');

        btn[0].onclick = function() {
            alert("点我干什么~"); // 移除事件后,该警示框只会做到第一次点击弹出,再点击不会弹出
            btn[0].onclick = null;
        }
        btn[1].addEventListener('click', fn1);

        function fn1() {
            alert('我也能弹出!'); // 移除事件后,该警示框只会做到第一次点击弹出,再点击不会弹出
            btn[1].removeEventListener('click', fn1)
        }
        btn[2].attachEvent('onclick', fn2);
    </script>
</body>

兼容性删除事件方法:

function removeEventListener(element, eventName, fn) {
            // 判断当前浏览器浏览器是否支持removeEventListener方法
            if (element.removeEventListener) {
                element.removeEventListener(eventName, fn);
            } else if (element.detachEvent) {
                element.detachEvent('on' + eventName, fn);
            } else {
                element['on' + eventName] = null;
            }
        }    

DOM事件流

事件流描述的是从页面中接收事件的顺序
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流;
如给一个按钮注册了点击事件:

DOM事件流分为3个阶段:
    1、捕获阶段 2、当前目标阶段 3、冒泡阶段

    事件冒泡:IE最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到DOM最顶级节点的过程
    事件捕获:网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到最具体的元素接收的过程;
   注意:
    JS代码中只能执行捕获或者冒泡其中的一个阶段;
    传统注册方式和attachEvent方式只能得到冒泡阶段;
    addEventListener(type, listener[, useCapture])第三个参数useCapture若是true,表示在事件捕获阶段调用事件处理程序;若是false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序;

    实际开发中,很少使用事件捕获,更关注事件冒泡;
    有些事件是没有冒泡的,如onblur、onfocus、onmouseover

<body>
    <div class='father'>这是一个测试案例
        <div class='son'>点我</div>
    </div>
    <script>
        var divs = document.querySelectorAll('div');
        // 将useCapture设置为true,为捕获阶段,则从顶层往下传递
        divs[0].addEventListener('click', function() {
            alert('这是父级标签~');
        }, true)
        divs[1].addEventListener('click', function() {
                alert('这是子级标签~');
            }, true)
            // 此时点击父级内容,则只弹出'这是父级标签'
            // 点击子级内容,则先弹出父级标签,再弹出子级标签
    </script>
</body>
<body>
    <div class='father'>这是一个测试案例
        <div class='son'>点我</div>
    </div>
    <script>
        var divs = document.querySelectorAll('div');
        // 将useCapture设置为false,为冒泡阶段,则从底层往上传递
        divs[0].addEventListener('click', function() {
            alert('这是父级标签~');
        }, false)
        divs[1].addEventListener('click', function() {
                alert('这是子级标签~');
        }, false)
            // 此时点击父级内容,则只弹出'这是父级标签'
            // 点击子级内容,则先弹出父级标签,再弹出子级标签
    </script>
</body>

事件对象

event对象代表事件的状态,如键盘按键的状态、鼠标的位置、鼠标按钮的状态等;即事件发生后,跟事件相关的一系列信息数据的集合都放在这个对象里面,该对象即事件对象event,它有很多属性和方法,如:
  谁绑定了这个事件;
  鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置;
  键盘触发事件的话,会得到键盘的相关信息,如按了哪个键;

事件对象的使用语法

eventTarget.onclick = function(event) {
    // 这个event就是事件对象,可以将其写成e或evt
   }

该event是个形参,系统帮我们设定为事件对象,不需要传递实参过去,该event对象在注册事件时自动创建,并依次传递给事件监听器(事件处理函数)
事件对象的兼容性方案 
   事件对象本身的获取存在兼容问题:
    1、标准浏览器中是浏览器给方法传递的参数,只需要定义形参e(event)就可以获取到;
    2、在IE6-8中,浏览器不会给方法传递参数,若需要的话,需要到window.event中获取查到;
    解决: e = e || window.event;

常见事件对象的属性和方法

事件对象属性方法       说明
e.target返回触发事件的对象    (标准)
e.srcElment  返回触发事件的对象    (非标准 ie6-8使用)
e.type返回事件的类型 如click mouseover等 (不加on)
e.cancelBubble该属性阻止冒泡        (非标准 ie6-8使用)
e.preventDefault()      该方法阻止默认事件     (标准,如不让链接跳转)
e.ruturnValue            该属性阻止默认事件     (非标准,如不让链接跳转)
e.stopPropagation()   阻止传播,不管是冒泡还是捕获阶段
e.stopImmediatePropagation一个节点同时绑定多个同类事件,阻止同类事件
  • e.target 

e.target返回触发事件的对象(元素) 注意:和eventTarget不是一回事,eventTarget是事件绑定的对象;如下示例:

<body>
    <ul>
        <li>小红</li>
        <li>小明</li>
    </ul>
    <script>
        var ul = document.querySelector('ul');
        ul.onclick = function(e) {
            alert('看看是谁处理~');
            console.log(e.target); // 可以是ul下的任意一个元素触发,如<li>小红</li>
            console.log(this); // 因为事件绑定在ul上,此时this即ul  
        }
    </script>
</body>
  • e.type

e.type返回事件对象的属性和方法

<body>
    <button>测试</button>
    <script>
        var button = document.querySelector('button');
        button.addEventListener('click', fun);

        function fun(e) {
            alert('111');
            console.log('这是一个测试');
            console.log(e.type); // click
        }
    </script>
</body>
  • 阻止默认事件产生e.preventDefault()、e.returnValue

e.preventDefault()方法和e.returnValue属性阻止默认行为的发生,如让链接不跳转,或者让提交按钮不提交;后者应用于低版本浏览器;

<body>
    <a href="http:www.baidu.com">百度</a>
    <script>
        var as = document.querySelector('a');
        as.addEventListener('click', function(e) {
            // e.preventDefault(); // 不会在触发提交作用
            e.returnValue;  // 不会再触发提交作用,适用于低版本
        })
    </script>
</body>

禁止鼠标右键弹出菜单栏 contextmenu

contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单

  <script>
        document.addEventListener('contextmenu', function(e) {
            e.preventDefault(); // 则不会弹出右键菜单
        })
  </script>

禁止鼠标选中selectStart

selectStart用于鼠标开始选中

<body>
    <div>selectstart阻止了,则内容就不能被选中</div>
    <script>
        document.addEventListener('selectstart', function(e) {
            e.preventDefault(); // 则页面内容就不会被选中,不能用于复制功能
        })
    </script>
</body>
  • 阻止事件冒泡e.stopPropagation()、e.cancelBubble

阻止事件冒泡有两种方式,一种是利用事件对象里面的stopPropagation方法;另一种是使用事件对象的cancelBubble属性(适用于低版本浏览器);

<body>
    <div class='father'>这是一个测试案例
        <div class='son'>点我</div>
    </div>
    <script>
        var divs = document.querySelectorAll('div');
        // 将useCapture设置为true,为捕获阶段,则从顶层往下传递
        divs[0].addEventListener('click', function() {
            alert('这是父级标签~');
        }, false)
        divs[1].addEventListener('click', function(e) {
                alert('这是子级标签~');
                e.stopPropagation();
            }, false)
            // 此时点击父级内容,则只弹出'这是父级标签'
            // 点击子级内容,则只弹出子级标签,不会再弹出父级标签
    </script>
</body>

事件委托(代理、委派)

事件委托也称为事件代理,在jQuery里面称为事件委派;

原理:不对每个子节点设置事件监听器,而是事件监听器设置在父级节点上,然后利用冒泡原理影响设置每个子节点。

作用:只操作了一次DOM,提高了程序的性能;

<body>
    <ul>
        <li>小红</li>
        <li>小明</li>
    </ul>
    <script>
        var ul = document.querySelector('ul');
        ul.addEventListener('click', function(e) {
            alert('只给ul设置点击事件,利用事件冒泡影响每个节点~');
        })
    </script>
</body>

常用的鼠标与键盘事件对象

鼠标事件对象MouseEvent和键盘事件对象KeyboardEvent

鼠标事件对象说明
e.clientX返回鼠标相对于浏览器窗口可视区的X坐标
e.clientY返回鼠标相对于浏览器窗口可视区的Y坐标
e.pageX返回鼠标相对于文档页面(document)的X坐标
e.pageY返回鼠标相对于文档页面(document)的Y坐标
e.screenX返回鼠标相对于电脑屏幕的X坐标
e.screenY返回鼠标相对于电脑屏幕的Y坐标
<style>
        img {
            position: absolute;
            height: 40px;
            width: 40px;
        }
</style>


<body>
    <img src="imgs/draw.jpg" alt="">
    <script>
// 实现图片跟随鼠标移动效果
// 核心原理是每次鼠标移动获得的坐标赋值给图片的left和top值
        var img = document.querySelector('img');
        document.addEventListener('mousemove', function(e) {
            var x = e.pageX;
            var y = e.pageY;
            console.log(x, y);
            img.style.left = x + 'px';
            img.style.top = y + 'px'; // 这个一定要连接'px'
        })
    </script>
</body>
常用键盘事件触发条件
onkeyup键盘按键被松开时触发
onkeydown键盘按键被按下时触发
onkeypress键盘按键被按下时触发(但是他不识别功能键,如ctrl)

若使用addEventListener不需要加on;

keyup和keydown不识别大小写;

三个事件的执行顺序是:keydown---keypress---keyup

e.KeyCode可得到键盘按键的ASC码值;

以下代码实现如下功能(内容为空时只显示input框,有值时则放大显示):

     

 <style>
        .con {
            display: none; */
            font-size: 20px;
        }
</style>
<body>
    <div class='search'>
        <div class="con">123</div>
        <input class='index' type="text" placeholder="请输入您的快递单号">
    </div>
    <script>
        // input输入值时,con显示input内对应的大号内容,若input为空,则隐藏con
        var con = document.querySelector('.con');
        console.log(con);
        console.log(con.style);
        var ipt = document.querySelector('input');
        ipt.addEventListener('keyup', function() {
            if (ipt.value === '') {
                con.style.display = 'none';
            } else {
                con.style.display = 'block';
                con.innerHTML = ipt.value;
            }
        })
    </script>
</body>

操作元素

DOM操作可改变网页内容、结构和样式,可以利用DOM操作元素来改变元素里面的内容、属性等。

改变元素内容

可利用elment.innerText或element.innerHTML改变元素中的内容;前者改变从元素起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉;后者也可以改变元素从起始位置到终止的全部内容,但是它可改变标签中的html标签和空格、换行

<body>
    <!-- 事件源 按钮 -->
    <button id='btn'>点我!</button>
    <div>早上好</div>
</body>
<script>
    // 事件源 按钮
    var btn = document.getElementById('btn');
    var divs = document.querySelector('div');
    // 事件类型及事件处理
    btn.onclick = function() {
        // 点击按钮后,使用innerHTML方法 div内容变为晚安~,并加粗显示
        divs.innerHTML = '<strong>晚安~</strong>';
        // 点击按钮后,使用innerText方法 div内容变为<strong>晚安~</strong>
        divs.innerText = '<strong>晚安~</strong>';
    }
</script>

改变常用元素的属性

可通过DOM改变元素的属性,如src、href、title等

<body>
    <img src="imgs/draw.jpg" alt="">
    <div>drawing~</div>
</body>
<script>
    // 事件源 按钮
    var div = document.querySelector('div');
    var img = document.querySelector('img');
    // 事件类型及事件处理
    img.onclick = function() {
        // 点击图片后,div内容变为working~,图片变为work.jpg
        img.src = "imgs/work.jpg";
        div.innerText = 'working~';
    }
</script>

改变表单元素的属性

利用DOM可以改变表单元素的type/value/checked/selected/disabled属性;

注意表单里面的内容是通过value属性改变的~

<body>
    <button>点我!</button>
    <input type="text" value="请输入内容">
</body>
<script>
    var btn = document.querySelector('button');
    var ipt = document.querySelector('input');
    btn.onclick = function() {
        // 按钮点击后 表单文本改变
        ipt.value = '起风了~';
        // 按钮点击后 按钮被禁用,此处用this替代btn是因为该动作是btn执行的,this即表示btn
        // this 指向的是事件函数的调用者
        this.disabled = true;
    }
</script>

改变元素的样式属性

可通过JS修改元素的大小、颜色、位置等样式;通过element.style改变行内样式,通过element.className改变类名样式;使用element.style方式改变样式时,要注意style里面的属性要改为驼峰命名方式,如之前的背景样式为background-color,此处应该为backgroundColor;如字体为font-size,此时应该为fontSize;由于利用JS修改样式,产生的是行内样式,所以权重较高~

自定义属性的操作

获取属性值的方法有:

  • element.属性
  • element.getAttribute('属性');

区别:

第一种方法用于获取元素本身自带的属性;后者主要是为了获取自定义的属性(标准),即程序员自定义的属性;

设置属性值的方法有:

element.属性 = “值”  用于设置内置元素的属性;

element.setAttribute('属性',‘值’)  用于设置自定义元素的属性;

移除属性:

element.removeAttribute('属性');

H5自定义属性:

自定义属性是为了保D:\fronted\pink\arraytest.html
D:\fronted\pink\1209.html存并使用数据,有些数据可以保存到页面中而不用保存到数据库中;

H5规定自定义属性要以data-开头作为属性名并且赋值;

<div data-index='1'></div>
// 或使用JS设置
element.setAttribute('data-index', 2);

获取H5自定义属性:

新增element.dataset.index或者element.dataset['index'], ie11才开始支持;

节点操作

为什么要学习节点操作?

获取元素通常有两种方式:

  1. 利用DOM提供的方法获取元素,如document.getElementById()、document.getElementsByClassName()、document.querySelector等,但该方式逻辑性不强、且比较繁琐;
  2.  利用节点层级关系获取元素,如利用父子兄节点关系获取元素、逻辑性强,但是兼容性较差;

节点概述

    网页中的所有内容都是节点(如标签、属性、文本、注释等),在DOM中,节点使用node表示;
    HTML DOM树中的所有节点均可通过JavaScript进行访问,所有HTML元素(节点)均可被修改,也可以创建或删除。
  一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性
  元素节点的nodeType为1;属性节点的nodeType为2;文本节点的nodeType为3(文本节点包含文字、空格、换行等),在实际开发中,节点操作主要操作的是元素节点。

节点层级

  利用DOM树可把节点划分为不同的层级关系,常见的是父子兄层级关系。

  • 父级节点 node.parentNode

   parentNode属性可返回某节点的父节点,注意是最近的一个父节点,若指定的节点无父节点则返回null;

 <body>
   <div id = 'ids'>今天是个晴朗的日子</div> -->
   <ul>
    <li>好好学习</li>
    <li>天天向上</li>
    <li>报效祖国</li>
   </ul>
 </body>
 <script>
   var li = document.querySelector('li');
   console.log(li);
   var ul = li.parentNode;
   console.log(ul);
 </script>
  • 子级节点 parentNode.childNodes(标准)

parentNode.childNodes返回包含指定节点的子节点的集合,该集合为即时更新的集合;子集合包含所有的子节点,如元素节点、文本节点等

<body>
    <div id = 'ids'>今天是个晴朗的日子</div> -->
    <ul>
     <li>好好学习</li>
     <li>天天向上</li>
     <li>报效祖国</li>
    </ul>
 </body>
 <script>
    var ul = document.querySelector('ul');
    console.log(ul);
    var li = ul.childNodes;
    console.log(li); // 会把换行等一切子元素都查出来
 </script>

如果只想要获得里面的元素节点(nodeType为1),则需要专门处理所以一般不直接使用childNodes;

<body>
    <div id = 'ids'>今天是个晴朗的日子</div> -->
    <ul>
     <li>好好学习</li>
     <li>天天向上</li>
     <li>报效祖国</li>
    </ul>
 </body>
 <script>
    var ul = document.querySelector('ul');
    var arr = [];
    console.log(ul);
    for(var i = 0; i < ul.childNodes.length; i++) {
     if(ul.childNodes[i].nodeType === 1) {
      // console.log(ul.childNodes[i]);
      arr.push(ul.childNodes[i]);
     }
    }
    console.log(arr);
 </script>
  • 子级元素节点 parentNode.children(非标准) 

   parentNode.children是一个只读属性,返回所有的子元素节点。注意:该方法只返回子元素节点,其余节点类型不返回
   虽然该方法是一个非标准,但它得到了各个浏览器的支持,因此可以放心使用;

  • 第一个子节点 parentNode.firstChild

   parentNode.firstChild返回第一个子节点,找不到子节点则返回null。同样,也是包含所有的节点;

  • 最后一个子节点 parentNode.lastChild

   parentNode.lastChild返回最后一个子节点,找不到则返回null。同样,也是包含所有的节点;

  • 第一个子元素节点 parentNode.firstElementChild

   firstElementChild返回第一个子元素节点,找不到则返回null;ie9以上才支持

  • 最后一个子元素节点 parentNode.lastElementChild

   parentNode.lastElementChild返回最后一个子元素节点,找不到则返回null。ie9以上才支持
   实际开发中,经常使用parentNode.children[索引]方法获得指定位置的子元素节点,如获取第一个子元素节点:parentNode.children[0]
   获取最后一个子元素节点:parentNode.children[parentNode.children.length - 1];

  • 当前元素的下一个兄弟节点node.nextSibling

node.nextSibling返回当前元素的下一个兄弟节点,找不到则返回null,返回的结果包含所有的节点;

  • 当前元素的上一个兄弟节点node.previousSibling

node.previousSibling返回当前元素的上一个兄弟节点,找不到则返回null,返回的结果包含所有的节点;

  • 当前元素的下一个兄弟元素节点 node.nextElementSibling

 node.nextElementSibling返回当前元素下一个兄弟元素节点,找不到则返回null;ie9以上才支持

  • 当前元素的下一个兄弟元素节点 node.nextElementSibling

   node.previousElementSibling返回当前元素上一个兄弟元素节点,找不到则返回null;ie9以上才支持

所以要完美解决上述两种问题,要进行处理:

function getNextElementSibling(element) {
    var el = element;
    while(el = el.nextSibling) {
     if(el.nodeType === 1) {
      return el;
     }
    }
    return null;
   }

创建节点 

  • document.createElement('tagName')

   document.createElement()方法创建由tagName指定的HTML元素,因为这些元素原先不存在,是根据我们的需求动态生成的,所以也称为动态创建元素节点;

添加节点

  • node.appendChild(child)方法、 node.insertBefore(child,指定元素)

  node.appendChild(child)方法将一个节点添加到指定父节点的子节点列表末尾。node是父节点;
  node.insertBefore(child,指定元素)方法将一个节点添加到父节点的指定子节点前面。node是父节点;

<body>
    <div id = 'ids'>今天是个晴朗的日子</div>
    <ul>
     <li>好好学习</li>
     <li>天天向上</li>
     <li>报效祖国</li>
    </ul>
</body>
<script>
    var ul = document.querySelector('ul');
    var li = document.createElement('li');
    var li1 = document.createElement('li');
    // 在ul的最后一个li之后添加li1
    ul.appendChild(li1);
    // 在ul的第一个li之前添加li
    ul.insertBefore(li,ul.children[0]);
    console.log(ul);
</script>

删除节点

  •  删除节点 node.removeChild(child)

  node.removeChild(child)删除一个子节点,返回删除的节点。

复制节点

  •  复制节点node.cloneNode()

   node.cloneNode()方法返回调用该方法的节点的一个副本,也称为克隆节点/拷贝节点;
   若参数为空或false,则是浅拷贝,即只克隆节点本身,不克隆里面的子节点;
   若参数为true,则是深度拷贝,会复制节点本身及里面所有的子节点

三种动态创建元素区别

document.write()是直接将内容写入页面的内容流,但是文档流执行完毕,会导致页面全部重绘(重绘是指重新创建一个页面,原先的页面都没了);
element.innerHTML是将内容写入某个DOM 节点,不会导致页面全部重绘;该方法创建多个元素效率更高(不要采用拼接字符串方式,采取数组形式拼接),但结构稍复杂;
createElement()创建多个元素效率稍低一点点,但是结构更清晰;

<body>
    <div id = 'ids'>今天是个晴朗的日子</div>
    <ul>
     <li>好好学习</li>
     <li>天天向上</li>
     <li>报效祖国</li>
    </ul>
</body>
<script>
    var div = document.querySelector('div');
    var date = +new Date();
    // 采用拼接字符串形式
    // for (var i = 0; i<1000;i++) {
    //     div.innerHTML += '<strong>心情好呀心情好</strong>';
    // }
    // var date1 = +new Date();
    // var time = date1 - date;
    // console.log(time); // 510ms
    // 用数组形式形式
    var arr = [];
    for (var i = 0; i < 1000; i++) {
     arr.push('<strong>心情好呀心情好</strong>');
    }
    div.innerHTML += arr.join('')
    var date1 = +new Date();
    var time = date1 - date;
    console.log(time); // 1ms
</script>

示例

示例一:动态生成表格,点击删除按钮则会自动删除所在行

<body>
    <!-- 表格应该只有头部,行和列都应该自动生成放在tbody下 -->
    <table>
        <thead>
            <tr>
                <td>姓名</td>
                <td>性别</td>
                <td>年龄</td>
                <td>籍贯</td>
                <td>操作</td>
            </tr>
        </thead>
        <tbody>

        </tbody>
    </table>
</body>
<script>
    // 动态生成表格
    var datas = [{
        name: '小唐',
        sexual: '女',
        age: '18',
        nativePlace: 'SiChuan'
    }, {
        name: '小吴',
        sexual: '男',
        age: '20',
        nativePlace: 'ShanDong'
    }, {
        name: '小阳',
        sexual: '女',
        age: '18',
        nativePlace: 'AnHui'
    }, {
        name: '小曹',
        sexual: '男',
        age: '19',
        nativePlace: 'HeNan'
    }];
    // 将数据依次放在tbody里面的行
    var tbody = document.querySelector('tbody');
    for (var i = 0; i < datas.length; i++) {
        var tr = document.createElement('tr');
        tbody.appendChild(tr);
        for (var k in datas[i]) {
            var td = document.createElement('td');
            // 单元格存值
            td.innerHTML = datas[i][k];
            // 将单元格添加到行
            tr.appendChild(td);
        }
        // 删除操作独立创建,使用href="javascript:;方法可以避免页面跳转,并且不会使链接上面加#"
        var td1 = document.createElement('td');
        td1.innerHTML = '<a href="javascript:;"> 删除 </a>'
        tr.appendChild(td1);
    }
    // 点击删除按钮会删掉该行
    var as = document.querySelectorAll('a');
    for (var i = 0; i < as.length; i++) {
        as[i].onclick = function() {
            // as的父节点是td,td的父节点是tr,要删除tr(父亲的父亲)
            // this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode);
            tbody.removeChild(this.parentNode.parentNode);
        }
    }
</script>

示例二:在留言板上输入内容,发布后,自动显示留言列表

<body>
    <input type="text"></input>
    <button>发布</button>
    <ul></ul>
</body>

<script>
    // 留言板点击发布后,显示留言内容
    var button = document.querySelector('button');
    var ul = document.querySelector('ul');
    var input = document.querySelector('input');
    button.onclick = function() {
        console.log(input.value);
        if (input.value === '') {
            alert('请先输入内容,再发布!');
            return
        } else {
            var li = document.createElement('li');
            li.innerHTML = input.value;
            // 后发布的在留言板后面
            ul.appendChild(li);
        }
    }
</script>

示例三:鼠标滑过显示下拉框内容

<style>
    .nav,
    .lili {
        list-style: none;
        float: left;
    }
    
    li {
        list-style: none;
    }
</style>

<body>
    <ul class='nav'>
        <li class='lili'>
            <a href=" "> QQ</a>
            <ul>
                <li>
                    <a href="javascript:;">私信</a>
                </li>
                <li>
                    <a href="javascript:;">评论</a>
                </li>
                <li>
                    <a href="javascript:;">@我</a>
                </li>
            </ul>
        </li>
        <li class='lili'>
            <a href="javascript:;"> 微博</a>
            <ul>
                <li>
                    <a href="javascript:;">私信</a>
                </li>
                <li>
                    <a href="javascript:;">评论</a>
                </li>
                <li>
                    <a href="javascript:;">@我</a>
                </li>
            </ul>
        </li>
        <li class='lili'>
            <a href="javascript:;"> 微信</a>
            <ul>
                <li>
                    <a href="javascript:;">私信</a>
                </li>
                <li>
                    <a href="javascript:;">评论</a>
                </li>
                <li>
                    <a href="javascript:;">@我</a>
                </li>
            </ul>
        </li>
    </ul>
</body>

<script>
    // 鼠标经过显示下拉菜单
    var nav = document.querySelector('.nav');
    var lis = nav.children;
    for (var i = 0; i < lis.length; i++) {
        lis[i].onmouseover = function() {
            this.children[1].style.display = 'block';
        }
        lis[i].onmouseout = function() {
            this.children[1].style.display = 'none';
        }
    }
</script>
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迷糊的小小淘

整理不易,赏点动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值