极致DOM编程体验:JavaScript DOM基础理论解析和实践应用,让Web前端开发更加高效

1、介绍

1.1 什么是 DOM?

DOM 是 W3C(万维网联盟)的标准。

DOM 定义了访问 HTML 和 XML 文档的标准:

“W3C 文档对象模型 (DOM) 是中立于平台和语言的接口,它允许程序和脚本动态地访问和更新文档的内容、结构和样式。”

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

  1. 核心 DOM - 针对任何结构化文档的标准模型
  2. XML DOM - 针对 XML 文档的标准模型
  3. HTML DOM - 针对 HTML 文档的标准模型

编者注:DOM 是 Document Object Model(文档对象模型)的缩写。

1.2 什么是 HTML DOM?

HTML DOM 是:

  HTML 的标准对象模型

  HTML 的标准编程接口

W3C 标准

HTML DOM 定义了所有 HTML 元素的对象属性以及访问它们的方法。换言之,HTML DOM 是关于如何获取修改添加删除 HTML 元素的标准。

2、DOM的顶级对象是 document

 2.1 Document 对象常用的属性和方法

属性 / 方法描述

 document.getElementById

返回对拥有指定 id 的第一个对象的引用。

document.getElementsByTagName

返回带有指定标签名的对象集合。

document.querySelector

返回文档中匹配指定的CSS选择器的第一元素

document.querySelectorAll

HTML5中引入的新方法,返回文档中匹配的CSS选择器的所有元素节点列表

document.body

获取 body 元素

document.documentElement

获取 html 元素

2.2 使用例子

  document.getElementById ------  根据ID获取元素

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="time">2019-9-9</div>
  <script>
    // 1.因为我们文档页面从上往下加载,所以先得有标签 所以我们的script写在下面
    // 2.get 获取 element 元素 by 通过 驼峰命名法
    // 3.参数 id是大小写字母敏感的字符串
    // 4.返回的是一个元素对象  
    var timer = document.getElementById('time');
    console.log(timer);//输出的是一个对象
    console.log(typeof timer);//object
    // 5.console.dir(timer); 打印我们返回的元素对象 更好的查看里面的属性和方法
    console.dir(timer);
  </script>
</body>

</html>

document.getElementsByTagName ------ 根据标签名获取元素

<body>
    <ul>
        <li>知否知否,应是等你好久1</li>
        <li>知否知否,应是等你好久2</li>
        <li>知否知否,应是等你好久3</li>
        <li>知否知否,应是等你好久4</li>
        <li>知否知否,应是等你好久5</li>
    </ul>
    <ol id="ol">
        <li>生僻字</li>
        <li>生僻字</li>
        <li>生僻字</li>
        <li>生僻字</li>
        <li>生僻字</li>
    </ol>
    <script>
        // 返回的是 获取过来的元素对象的结合 以伪数组的方式存储的
        var lis = document.getElementsByTagName('li');
        console.log(lis);
        console.log(lis[0]);
        // 2.我们向要依次打印里面的元素对象我们可以采取遍历的方式
        for (var i = 0; i < lis.length; i++) {
            console.log(lis[i]);
        }
        // 3.如果页面只有一个li 返回的还是伪数组的形式
        // 4.如果页面中没有这个标签返回的是空的伪数组
        // console.log(lis);
        // 5.获取父元素指定的标签名
        var ol = document.getElementById('ol');
        console.log(ol.getElementsByTagName('li'));
    </script>
</body>

H5新增获取标签元素的方法 ------ document.querySelector 、document.querySelectorAll

<body>
    <div class="box">盒子</div>
    <div class="box">盒子</div>
    <div id="nav">
        <ul>
            <li>首页</li>
            <li>产品</li>
        </ul>
    </div>
    <script>
        // 1.getElementsByClassName  根据类名获取某些元素
        var boxs = document.getElementsByClassName('box');
        console.log(boxs);
        // 2.querySelector 返回指定选择器的第一个元素对象
        var firstBox = document.querySelector('.box');
        console.log(firstBox);
        var nav = document.querySelector('#nav');
        console.log(nav);
        var li = document.querySelector('li');
        console.log(li);
        // 3.querySelectorAll() 返回指定选择器的 所有元素对象集合
        var allBox = document.querySelectorAll('.box');
        console.log(allBox);
        var lis = document.querySelectorAll('li');
        console.log(lis);
    </script>
</body>

获取 body 和 html 元素 ------document.body 、document.documentElement

<body>
    <script>
        // 1.获取body 元素
        var bodyEle = document.body;
        console.log(bodyEle);
        console.dir(bodyEle);

        // 2.获取html 元素
        var htmlEle = document.documentElement;
        console.log(htmlEle);
    </script>
</body>

 3、事件

3.1 事件三要素

事件是由三部分组成  事件源  事件类型  事件处理程序  我们也称为事件三要素

  1. 事件源事件被触发的对象  谁 比如:按钮 
  2. 事件类型 如何触发 什么事件 比如鼠标点击事件(onclick) 
  3. 事件处理程序 通过一个函数赋值的方式 完成 

代码示例:

<body>
  <button id="btn">唐伯虎</button>
  <script>
    // 点击按钮,弹出对话框
    // 1.事件是由三部分组成  事件源  事件类型  事件处理程序  我们也称为事件三要素
    // (1).事件源事件被触发的对象  谁 比如:按钮
    var btn = document.getElementById('btn');
    // (2).事件类型 如何触发 什么事件 比如鼠标点击事件(onclick)
    // (3).事件处理程序 通过一个函数赋值的方式 完成
    btn.onclick = function () {
      alert('点秋香');
    }
  </script>
</body>

3.2 执行事件的步骤

步骤:

  1. 获取事件源
  2. 绑定事件 ,注册事件事件类型
  3. 添加事件处理程序

代码示例:

<body>
    <div>123</div>
    <script>
        // 执行事件的步骤
        // 点击div 控制台输出 我被选中了
        // 1.获取事件源
        var div = document.querySelector('div');
        //    2.绑定事件 注册事件 事件类型
        // div.onclick
        // 3.添加事件处理程序
        div.onclick = function () {
            console.log('我被选中了');
        }
    </script>
</body>

注意: 给元素绑定事件,处理函数内的 this 指向的是事件函数的调用者,也就是当前标签的对象的引用(比如:给button标签绑定事件,this就指向button标签)

3.3 常见的鼠标事件

事件名称说明

onclick

鼠标点击事件

onmouseover

鼠标经过触发

onmouseout

鼠标离开触发

onfocus

获取鼠标焦点触发

onblur

失去鼠标焦点触发

onmousemove

鼠标移动触发

onmouseup

鼠标弹起触发

onmousedown

鼠标按下触发

使用示例:

<body>
    <div>123</div>
    <script>
        var div = document.querySelector('div');
        div.onmousedown = function () {
            alert('我是你大爷!!!')
        }
    </script>
</body>

4、修改HTML标签的内容

实现方法:

  1. .innerTwxt  从起始位置到终点位置的内容,但它除去html标签,同时空格和换行会去掉
  2. .innerHTML  从起始位置到终点位置的内容,包括html标签,保留空格和换行

代码示例: 

<body>
  <button>显示当前系统时间</button>
  <div>显示系统时间的标签</div>
  <p></p>
  <script>
    // 改变页面元素1. div.innerTwxt  从起始位置到终点位置的内容,但它除去html标签,同时空格和换行会去掉
    // 改变页面元素2. div.innerHTML  从起始位置到终点位置的内容,包括html标签,保留空格和换行
    // 当我们点击了按钮,div里面的元素发生变化
    // 1.获取元素
    var btn = document.querySelector('button');//获取按钮标签
    var div = document.querySelector('div');//获取div标签
    var p = document.querySelector('p')

    // 给button按钮绑定点击事件, 利用 .innerHTML 修改标签内容
    btn.onclick = function () {
      div.innerHTML = '<strong>日期:</strong>' + getDate();
    }

    // 封装一个时间日期函数 
    function getDate() {
      // 格式化日期 年月日
      var date = new Date();
      var year = date.getFullYear();//年
      var month = date.getMonth() + 1;//月
      var dates = date.getDate();//日
      var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
      var day = date.getDay();//周几
      return ('今天是:' + year + '年' + ' ' + month + '月' + ' ' + dates + '日' + ' ' + arr[day]);
    }
    // 利用 .innerText 修改标签内容
    p.innerText = getDate();
  </script>
</body>

innerTextinnerHTML 的区别

修改数据的区别

  1. innerText 不识别 HTML 标签 非标准  会去除空格和换行
  2. innerHTML  可以识别 HTML 标签  W3C标准

获取数据的区别

  1. innerText 会去掉html标签
  2. innerHTML 保留html标签 空格和换行

代码示例: 

<body>
  <div></div>
  <p>我是文字
    <span>123</span>
  </p>
  <script>
    var div = document.querySelector('div');
    // 1. innerText 不识别 HTML 标签 非标准  会去除空格和换行
    // div.innerText = '<strong>今天是</strong>:2021'
    //2. innerHTML  可以识别 HTML 标签  W3C标准
    div.innerHTML = '<strong>今天是</strong>:2021'
    // 这个属性是可读写的 可以获取元素里面的内容
    var p = document.querySelector('p')
    // innerText 会去掉html标签
    console.log(p.innerText) //我是文字123
    // innerHTML 保留html标签 空格和换行
    console.log(p.innerHTML) //我是文字<span>123</span

  </script>
</body>

5、修改HTML标签的属性

5.1 显示内容属性

比如:srctitlevaluedisabled

srctitle  代码示例:

<style>
  img {
    height: 400px;
  }
</style>
<body>
  <button id="ldh">刘德华</button>
  <button id="zxy">张学友</button>
  <br>
  <img src="img/liudehu.jpg" alt="图片加载失败">
  <script>
    // 1.获取元素
    var ldh = document.getElementById('ldh');
    var zxy = document.getElementById('zxy');
    var img = document.querySelector('img');
    //  2.注册事件 处理程序
    ldh.onclick = function () {
      img.src = "img/liudehu.jpg";
      img.title = '刘德华';
    }
    zxy.onclick = function () {
      img.src = "img/zhangxueyuo.jpg";
      img.title = '张学友';
    }
  </script>
</body>

valuedisabled  代码示例:

<body>
  <button>按钮</button>
  <input type="text" value="输入内容">
  <script>
    // 1.获取元素
    var btn = document.querySelector('button');
    var input = document.querySelector('input');
    //2.注册事件 处理程序
    btn.onclick = function () {
      // 表单里的值 文字内容是通过value 来修改的
      input.value = '被点击了';
      // 如果想要某个表单被禁用 不能再点击  我们想要button这个按钮被禁用
      // btn.disabled = true;
      this.disabled = true;
  // this 指向的是事件函数的调用者,也就是 button 对象的引用
    }
  </script>
</body>

案列.仿京东显示密码

实现思路:

  • 点击眼睛按钮,把密码框类型改成文本框就可以看到里面的密码
  • 一个按钮两个状态,点击一次,切换为文本框,继续点击一次切换为密码框
  • 算法: 利用一个flag变量,来判断flag的值,如果是1就切换为文本框,flag 设置为0,如果是0就设置成密码框,flag设置为1

代码: 

<style>
  .box {
    position: relative;
    width: 400px;
    border-bottom: 1px solid #ccc;
    margin: 100px auto;
  }

  .box input {
    width: 370px;
    border: 0;
    /* 取消表单点击轮廓 */
    outline: none;
  }

  .box img {
    position: absolute;
    top: 2px;
    right: 2px;
    width: 20px;
  }
</style>

<body>
  <div class="box">
    <label for="">
      <img src="img/by.png" alt="眼睛" id="ete">
    </label>
    <input type="password" name="" id="pwd">
  </div>
  <script>
    //    1.获取元素
    var ete = document.getElementById('ete');
    var pwd = document.getElementById('pwd');
    // 2.注册事件 处理程序
    var flag = 0;
    ete.onclick = function () {
      // this.src = '';
      if (flag == 0) {
        this.src = 'img/ky.png'
        pwd.type = 'text';
        flag = 1;
      } else {
        this.src = 'img/by.png'
        pwd.type = 'password';
        flag = 0;
      }

    }

  </script>
</body>

 5.2 修改标签样式 style

通过 JS 修改的style 样式操作,产生的是行内样式,css 的权重比较高

代码示例 :

<style>
  div {
    width: 200px;
    height: 200px;
    background-color: pink;
  }
</style>

<body>
  <div></div>
  <script>
    // 1.获取元素
    var div = document.querySelector('div');
    // 2.注册事件 处理程序
    var flag = 0;
    div.onclick = function () {
      if (flag == 0) {
        this.style.backgroundColor = 'purple';
        this.style.width = '200px';
        flag = 1;
      } else {
        // div.style里面的属性 采取驼峰命名法
        this.style.backgroundColor = 'pink';
        this.style.width = '250px';
        flag = 0;
      }
      // JS 修改的style 样式操作,产生的是行内样式,css 的权重比较高
    }
  </script>
</body>

5.3  修改标签样式名称 class

 如果要修改的样式比较多,就可以用这种方式

代码示例:

<style>
  div {
    width: 200px;
    height: 200px;
    background-color: pink;
  }

  .con {
    background-color: purple;
    width: 100px;
    height: 100px;
    margin: 100px auto;
  }

  .fn {
    line-height: 100px;
    font-size: 20px;
    color: red;
  }
</style>

<body>
  <div class="fn">文本</div>
  <script>
    // 1.使用 element.style 获得修改元素样式 如果样式比较多代码太多
    var test = document.querySelector('div');
    test.onclick = function () {
      // this.style.backgroundColor = 'purple';

      // 2.使用element.className  获得修改元素样式 点击之后为div添加类名 con 使用于样式比较多
      // 使用element.className 会直接更改以前的类名 会覆盖掉以前的 id的不影响
      this.className = 'con';
      // 如果想保留之前的类名 可以使用多类名选择器
      this.className = 'fn con';
    }
  </script>
</body>

 6、排他思想

干掉所有人,留下我自己

代码示例:

<body>
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <button>按钮4</button>
    <button>按钮5</button>
    <script>
        // 1.获取所有按钮元素
        var btns = document.getElementsByTagName('button');
        // btns得到的是伪数组 里面的每一个元素 btns[i]
        for (var i = 0; i < btns.length; i++) {
            btns[i].onclick = function () {
                // console.log('11');
                // (1)我们去除所有的背景颜色(干掉其它人)
                for (var i = 0; i < btns.length; i++) {
                    btns[i].style.backgroundColor = '';
                }
                // (2)然后才让当前的背景颜色为pink(留下我自己)
                this.style.backgroundColor = 'pink';
            }
        }
        // 首先:干掉其它人  再到:留下我自己
    </script>
</body>

7、自定义属性

介绍:

自己添加的属性就是自定义属性,如:<div id="demo" index="1"></div> 这里的 index 就是自定义属性

7.1 获取自定义属性

<body>
  <div id="demo" index="1"></div>
  <script>
    var div = document.querySelector('div');
    // 1.获取元素的属性值
    // (1)element.属性
    console.log(div.id);
    // (2)element.getAttribut('属性') get得到获取 attribut属性 
    // 自己添加的属性就是自定义属性
    console.log(div.getAttribute('id'));
    console.log(div.getAttribute('index'));
  </script>
</body>

7.2 设置和移除自定义属性

<body>
  <div id="demo" index="1"></div>
  <script>
    var div = document.querySelector('div');
    // 1.获取元素的属性值
    // (1)element.属性
    console.log(div.id);
    // (2)element.getAttribut('属性') get得到获取 attribut属性 我们程序员
    // 自己添加的属性就是自定义属性
    console.log(div.getAttribute('id'));
    console.log(div.getAttribute('index')) // 1
    // 2.设置元素属性值
    // (1)element.属性='值';
    div.id = 'test';
    // 添加了一个class='navs' 类名 如果原来有的话就会被修改掉
    div.className = 'navs';
    // (2)element.setAttribute('属性','值');主要针对自定义属性
    div.setAttribute('index', 2);
    console.log(div.getAttribute('index')) // 2
    div.setAttribute('class', 'footer');//class 特殊 这里写的就是class 不是 className
    // 3.移除属性 removeAttribute('属性')
    div.removeAttribute('index');

  </script>
</body>

7.3 H5自定义属性

介绍:

  1. H5自定义属性:是为了保存并使用数据。有些数据可以保存到页面中,而不是保存到数据库中 。
  2. 自定义属性获取是通过getAttribute('属性')获取。
  3. 但是有些自定自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性
  4. H5规定自定义属性 data-开头 的作为属性名并且赋值 ,比如:<div data-index="1"></div>或者使用JS设置 element.setAttribute('data-index',2)

  5. 获取属性H5新增:element.dataset.index 或者 element.dataset['index']  ie 11才支持

     代码示例:

<body>
    <div data-time="5" data-getTim="20" data-list-name="andy"></div>
    <script>
        var div = document.querySelector('div');
        console.log(div.getAttribute('data-getTime'));
        div.setAttribute('data-index', 2);
        console.log(div.getAttribute('data-index'));
        // H5新增获取自定义属性的方法
        console.log(div.dataset.time);
        console.log(div.dataset.index);
        console.log(div.dataset['time']);
        // dataset 是一个集合里面存放了所有以data开头的自定义属性
        console.log(div.dataset);

        console.log(div.getAttribute('data-list-name'));
        // 如果自定义属性里有多个-链接的属性名 要用驼峰写法
        console.log(div.dataset.listName);
        console.log(div.dataset['listName']);
    </script>
</body>

8、节点

8.1 介绍:

  • 页面中的所有内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用 node 来表示。
  • HTML DOM 树中的所有的节点均可通过 HavanaScript 进行访问,所有的HTML元素(节点)均可被修改,也可以创建或删除
  •  一般的,节点至少拥有 nodeType (节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性

8.2 nodeType 

  • 元素节点 nodeType 为1
  • 属性节点 nodeType 为2
  • 文本节点 nodeType 为3(文本节点包含文字、空格、换行等)
  • 我们在实际开发中,节点操作主要操作的是元素节点

代码示例: 

<body>
  <!-- 节点的优点 -->
  <div>我是div</div>
  <span>我是span</span>
  <ul>
    <li>我是li</li>
    <li>我是li</li>
    <li>我是li</li>
    <li>我是li</li>
  </ul>
  <div class="box">
    <span class="reweima">x</span>
  </div>
  <script>
    var box = document.querySelector('.box');
    // console.dirxml()用来显示网页的某个节点(node)所包含的html/xml代码。
    console.dir(box);
  </script>
</body>

8.3 节点操作

节点操作之父节点  node.parentNode

<body>
    <div>我是div</div>
    <span>我是span</span>
    <ul>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
    </ul>
    <div class="demo">
        <div class="box">
            <span class="erweima">x</span>
        </div>
    </div>

    <script>
        // 1.父节点 parentNode
        var erweima = document.querySelector('.erweima');
        // var box = document.querySelector('box');
        // erweima 的父节点
        erweima.parentNode;//得到的是离元素最近的父级  这里可以直接拿到 box  
        console.log(erweima.parentNode);
    </script>
</body>

节点操作之子节点  parentNode.childNodes (标准)

parentNode.childNodes  返回包括指定节点的子节点的集合,该集合为及时更新的集合

<body>
    <div>我是div</div>
    <span>我是span</span>
    <ul>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
    </ul>
    <ol>
        <li>我是ol的li</li>
        <li>我是ol的li</li>
        <li>我是ol的li</li>
        <li>我是ol的li</li>
        <li>我是ol的li</li>
    </ol>
    <div class="demo">
        <div class="box">
            <span class="erweima">x</span>
        </div>
    </div>
    <script>
        /* nodeType(节点类型)
       元素节点 nodeType 为1
        属性节点 nodeType 为2
        文本节点 nodeType 为3 */
        // DOM 提供的方法(API)获取
        var ul = document.querySelector('ul');
        var lis = ul.querySelectorAll('li');
        // 1.子节点 childNodes(标准) 获得所有的子节点 包含 元素节点 和子节点、文本节点(文本节点包含文字、空格、换行等)等等
        console.log(ul.childNodes);
        // 2.子节点 children(非标准) 获取所有的子元素节点 也是我们实际开发常用的
        console.log(ul.children);

    </script>
</body>

子节点-第一个子元素和最后一个子元素

关键字:

  • firstChild 获取元素第一个节点,早不到返回NULL 同样也是包含所有的节点
  • lastChild  获取元素最后一个节点
<body>
    <ol>
        <li>我是li1</li>
        <li>我是li2</li>
        <li>我是li3</li>
        <li>我是li4</li>
    </ol>
    <script>
        var ol = document.querySelector('ol');
        // 1.firstChild 获取的是 第一个子节点 不管是文本节点还是元素节点
        console.log(ol.firstChild);
        // 2.lastChild  获取元素最后一个节点
        console.log(ol.lastChild);
        // 以下俩个节点有兼容性问题,IE9以上才支持
        // 3.返回的是 第一个子元素节点
        console.log(ol.firstElementChild);
        // 4.lastElementChild 返回的是 最后一个子元素节点
        console.log(ol.lastElementChild);
        // 5.实际开发的写法 既没有兼容性问题又能放回第一个子元素
        console.log(ol.children[0]);
        // 返回的是 最后一个子元素节点
        console.log(ol.children[ol.children.length - 1]);
    </script>
</body>

兄弟节点  node.nextSibling

<body>
    <div>我是div</div>
    <span>我是span</span>
    <span>我是span1</span>
    <script>
        var div = document.querySelector('div');
        var span = document.querySelector('span')
        // 1.nextSibling 得到的是下一个兄弟节点 包含元素节点、文本节点等等
        console.log(div.nextSibling);
        // 2.previousSibling 得到的是上一个兄弟节点 包含元素节点、文本节点等等
        console.log(div.previousSibling);
        // 以下的 IE9 以上才支持
        // 3.nextElementSibling 得到的是下一个兄弟元素节点 找不到返回null
        console.log(div.nextElementSibling);
        // 4.previousElementSibling  得到的是上一个兄弟元素节点
        console.log(span.previousElementSibling);
        // 解决兼容性的方案
        function getNextElementSibling(element) {
            var el = element;
            // nextElementSibling 得到的是下一个兄弟元素节点
            while (el = el.nextElementSibling) {
                if (el.nodeType == 1) {//元素节点的类型是1  nodeType节点类型
                    return el;
                }
            }
            return null;
        }
        var fn = getNextElementSibling(div);
        console.log(fn);
    </script>
</body>

创建添加节点

语法:

  •  创建元素节点 document.createElement()
  • 添加节点 node.appendChild(child) 方法将一个节点添加到指定父节点的字节点列表末尾,类似于css里面的after 伪元素
<body>
    <ul>
        <li>123</li>
    </ul>
    <script>
        //   1.创建元素节点 document.createElement()
        var li = document.createElement('li');
        // 2.添加节点 node.appendChild(child) node父级 child子级
        var ul = document.querySelector('ul') // 获取到父级的 DOM
        ul.appendChild(li);//后面添加元素
        // 3.添加节点 node.insertBefore(child,指定添加的位置)   
        var lili = document.createElement('li');
        ul.insertBefore(lili, ul.children[0]); // children获取所有的子元素节点
    </script>
</body>

删除节点  node.removeChild(child) 

node.removeChild(child)  方法从DOM 中删除一个子节点,返回删除的节点 删除节点中的子节点

<body>
  <button>删除</button>
  <ul>
    <li>熊大</li>
    <li>熊二</li>
    <li>光头强</li>
  </ul>
  <script>
    // 1.获取元素
    var ul = document.querySelector('ul');
    // 2.删除节点
    // ul.removeChild(ul.children[0]);
    // 3.点击按钮依次删除
    var btn = document.querySelector('button');
    btn.onclick = function () {
      // 如果想要某个表单被禁用 不能再点击 disabled 我们想要button这个按钮被禁用
      // btn.disabled = true;
      if (ul.children.length == 1) {
        alert('大爷手下留节~~')
        btn.disabled = true //禁用按钮
      } else {
        ul.removeChild(ul.children[0]);
      }

    }
  </script>
</body>

克隆节点  onde.cloneNode()

onde.cloneNode() 节点克隆(复制) 

  • 如果括号里面的内容为空或者为false,则为浅拷贝,既只克隆节点本身,不克隆里面的字节点
  • 如果括号里面的内容为空或者为true,则为深拷贝,复制标签里面的内容
<body>
    <ul>
        <li>1234</li>
        <li>2</li>
        <li>3</li>
    </ul>
    <script>
        var ul = document.querySelector('ul');
        // var lili = ul.children[0].cloneNode(); // 默认是false
        var lili = ul.children[0].cloneNode(true);
        ul.appendChild(lili);后面添加元素
    </script>
</body>

 9、三种创建元素方式的区别

1. document.write() 创建元素

document.write是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘

2. innerHTML  创建元素 

innerHTML创建多个元素效率更高(前提是不要采取字符串拼接,采取数组形式拼接)。结构稍微复杂

3. document.createElement() 创建元素

document.createElement()创建多个元素效率稍微低一点点。结构稍微清晰一点

<body>
  <button>点击</button>
  <p>abc</p>
  <div class="inner"></div>
  <div class="create"></div>
  <script>
    // 三种创建元素方式的区别
    // 1.document.write() 创建元素
    var btn = document.querySelector('button');
    btn.onclick = function () {
      document.write('<div>123</div>');
    }

    // 2.innerHTML  创建元素
    var inner = document.querySelector('.inner');
    // for (var i = 0; i < 5; i++) {                  
    //     inner.innerHTML += '<a href="#">百度</a>' + '<br>';  创建多个元素时效率低不采用
    // }
    var arr = [];
    for (var i = 0; i <= 100; i++) {
      arr.push('<a href="#">百度</a>');
    };//数组转换为字符串
    // join() 方法用于把数组中的所有元素转换一个字符串。 元素是通过指定的分隔符进行分隔的。
    inner.innerHTML = arr.join('');//不写就是没有分隔符  数组自带逗号分隔符 我们去掉


    // 3.document.createElement() 创建元素
    var create = document.querySelector('.create');
    for (var i = 0; i < 5; i++) {
      var a = document.createElement('a');
      create.appendChild(a);
    }

    // 经典面试题
  </script>
</body>

10、DOM重点核心

介绍:

  • DOM文档对象模型(简称:DOM)获取过来的节点都是对象 
  • 文档:整个页面就是文档   
  • 元素:html标签就是元素  
  • 节点页面所有的东西都是节点
  • 关于DOM操作我们主要针对元素操作。具体主要有: 、属性操作事件操作

注意:以下只是总结操作DOM的方法,如需看使用例子请往上翻找 ,也可以使用 ctrl + f 键进行快速查找。

10.1  创建 DOM 元素 

  1. document.write()  创建元素  
  2. node.innerHTML  创建元素  
  3. document.createElement()  创建元素

区别:

  • document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘 
  • innerHTML 创建多个元素效率更高(前提是不要采取字符串拼接,采取数组形式拼接)。结构稍微复杂
  • document.createElement() 创建多个元素效率稍微低一点点。结构稍微清晰一点

10.2 添加 DOM 元素 

node.appendChild(child) 添加到指定父节点的字节点列表末尾

参数: node 父节点    child 子节点

node.insertBefore(child,index)   添加到指定的位置

参数:node 父节点   child 子节点  index  指定添加的位置

10.3 移除 DOM 元素 

node.removeChild(child

参数:node 父节点   child 子节点  

10.4 修改 DOM 元素 

主要修改dom的元素属性,dom元素的内容、属性、表单的值等等

  • 修改元素属性:src、href、title等
  • 修改普通元素内容:innerHTML(保留空格和换行)、innerText
  • 修改表单元素:value、type、disabled等  // btn.disabled = true;表单被禁用 
  • 修改元素样式: style、className

 10.5 查询 DOM的元素

  •  DOM提供的API方法:getElementByIdgetElementsByTagName 古老用法 不推荐
  •  H5提供的新方法:querySelectorquerySelectorAll   提倡
  •  利用节点操作的获取元素:父( parentNode )、子( children )、兄( previousElementSibling (得到的是上一个兄弟元素节点)、nextElementSibling(得到的是下一个兄弟元素节点))

 10.6 属性操作

  主要针对自定义属性,自己添加的属性就是自定义属性

  • setAttribute  设置dom的属性值   div.setAttribute('data-index', 2)
  • getAttribute  得到dom的属性值  element.getAttribut('属性') 
  • removeAttribute   移除属性 removeAttribute('属性')

10.7 事件操作

给元素注册事件,采取事件源.事件类型=事件处理程序

事件类型事件名称
onclick       鼠标点击事件 
onmouseover  鼠标经过触发
onmouseout     鼠标离开触发
onfocus       获取鼠标焦点触发
onblur        失去鼠标焦点触发
onmousemove   鼠标移动触发
onmouseup     鼠标弹起触发
onmousedown   鼠标按下触发

11、注册事件(绑定事件)

注册事件有两种方式

传统的方式和方法监听注册方式

传统注册方式:

     利用on开头的事件onkclick 

<button onclick="alert('hi'~)"></button>

var btn = document.querySelectorAll('button');

 btn.onclick=function(){}

 特点:

注册事件的唯一性,同一个元素同一个事件只能设置一个处理函数,最后注册的处理程序将会覆盖前面注册的处理程序 

方法监听注册方式:

W3C 标准 推荐的方式

addEventListener()  它是一个方法

IE9之前IE不支持此方法,可以使用attachEvent()代替

特点:

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

语法:

eventTarget.addEventListener('type',listener[,usecapture])

eventTarget.addEventListener() 方法将指定的监听器注册到eventTarget(目标对象)

当该对象触发指定的事件时,就会执行事件处理函数。

该方法接收三个参数:

  1. type:事件类型字符串,比如click、mouseover,注意这里不要带on
  2. listener:事件处理函数,事件发生时,会调用该监听函数
  3. useCapture:可选参数,是一个布尔值,默认是false.

代码示例:

<body>
    <button>传统注册事件</button>
    <button>方法监听注册事件</button>
    <button>IE9以前的</button>
    <script>
        var btns = document.querySelectorAll('button');
        // 传统注册方式
        btns[0].onclick = function () {
            alert('hi~');
        }
        btns[0].onclick = function () {
            alert('Hi~');//会覆盖前面的
        }
        // 2.利用事件监听注册事件  iE9 以上才支持
        // (1)里面的事件类型是字符串,必定加''  不带on
        //  (2) 同一个元素 同一个事件可以添加多个侦听器(事件处理程序)
        btns[1].addEventListener('click', function () {
            alert('Hi~');
        })
        btns[1].addEventListener('click', function () {
            alert('你好~');//不会覆盖前面的
        })
        // 3.IE9以下的可以使用eventTarget.attachEvent(eventNamewithOn,callback) (不支持使用)
        // eventTarget.attachEvent()方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发
        // 指定的事件时,指定的回调函数就会被执行
        // 该方法接收两个参数:
        // (1).eventNamewithOn: 事件类型字符串,比如onclick、onmouseover,这里要带on
        // (2).callback: 事件处理函数,当目标触发事件时回调函数
        // attachEvent ie9 以前的版本支持
        btns[2].attachEvent('onclick', function () {
            alert(11);
        });
    </script>
</body>

12、删除事件( 解绑事件 )

 1. 传统方式解绑事件
      divs[0].onclick = null

2. removeEventListener 删除事件
      divs[1].removeEventListener('click', fn);

<style>
  div {
    width: 50px;
    height: 100px;
    background-color: pink;
  }
</style>

<body>
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <script>
    var divs = document.querySelectorAll('div');
    divs[0].onclick = function () {
      alert(11);
      //1.传统方式解绑事件
      divs[0].onclick = null;
    }
    //2. addEventListener 利用事件监听注册事件
    divs[1].addEventListener('click', fn)//里面的fn不需要调用加小括号()
    function fn() {
      alert(22);
      // removeEventListener 删除事件
      divs[1].removeEventListener('click', fn);
    }


  </script>
</body>

 13、DOM事件流

介绍:

     事件流:描述的是从页面中接收事件的顺序。

     事件发生时会在元素节点之间按照特定的顺序传播,这个传播的过程即DOM事件流。

DOM 事件流分为3个阶段:

  1. 捕获阶段  网景最早提出的:从最顶层的节点开始,然后逐级向下传播到最具体的元素(目标点)接收的过程
  2. 当前目标阶段  找到点击事件时就是目标阶段  
  3. 冒泡阶段 IE最早提出的: 事件开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层节点的过程

事件捕获冒泡理解:

通俗的点的解释:我们向水里扔一块石头,首先它会有一个下降过程,这个过程就可以理解为从最顶层向事件发生最具体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点向上冒(最具体的元素漂浮在水面),这个过程相当于事件冒泡。

代码示例:

<style>
  .father {
    position: relative;
    width: 200px;
    height: 200px;
    background-color: pink;
    margin: 100px auto;
  }

  .father .son {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 100px;
    height: 100px;
    background-color: purple;
    text-align: center;
    line-height: 100px;
  }
</style>

<body>
  <div id="app" v-cloak>
    <div class="father" @click.capture="fatherClick">
      <div class="son" @click="sonClick">son盒子</div>
    </div>
  </div>
  <script>
    const app = new Vue({
      el: '#app',
      data: {},
      methods: {
        sonClick() {
          /*  
           默认情况下:点击son盒子时冒泡阶段 先执行 sonClick方法 再到 fatherClick方法
           执行过程: son(目标)->father ->body ->html-> document  
           打印:
                先:son盒子事件触发了
                后:father盒子事件触发了
           */
          console.log('son盒子事件触发了')
          /* 
           给 father 盒子的点击事件加了 .capture 修饰符 开启事件捕获
           点击son盒子时捕获阶段 先执行 fatherClick方法 再到 sonClick方法
           过程:document-> html -> body -> father(目标) ->son(目标)
             打印:
                先:father盒子事件触发了
                后:son盒子事件触发了
        */
        },
        fatherClick() {
          console.log('father盒子事件触发了')
        }
      }
    })

  </script>

注意:

  1. JS代码中只能执行捕获或者冒泡其中的一个阶段。
  2. 实际开发中我们很少使用使用事件捕获,我们更关注事件冒泡
  3. 有些事件没有冒泡,比如onblur、onfocus、onmouseenter、onmouseleave、 onblur 、onfocus    

14、事件对象

14.1 介绍:

  1. event 就是一个事件对象 写到侦听函数的小括号里面当形参来看
  2. 事件对象只有调用了事件才会存在,它是系统给我们自动创建的不需要我们传递参数
  3. 事件对象是我们事件的一系列相关数据的集合,比如:鼠标点击里面就包含了鼠标的相关信息,鼠标坐标,如果是键盘事件就包含了键盘事件的信息 比如 判断用户按下了那个键
  4. 这个事件对象我们可以自己重命名 比如:event、ent、e
  5. 事件对象也有兼容性的问题 ie678 通过window.event 来获取对象   兼容性写法 e = e || window.event;

代码示例:

<style>
  div {
    width: 100px;
    height: 100px;
    background-color: pink;
  }
</style>

<body>
  <div>123</div>
  <script>
    // 事件对象
    var div = document.querySelector('div');
    div.onclick = function (e) {
      // console.log(event);
      // console.log(window.event);//ie678 规定写法
      // 兼容性写法
      e = e || window.event;
      console.log(e);
    }
    div.addEventListener('click', function (e) {
      console.log(e);
    })
  </script>
</body>

14.2 常见事件对象属性方法

事件属性或方法 

说明 

e.target

返回触发事件的对象  标准

e.srcElement 

返回触发事件的对象  非标准  ie6-8使用

e.type 

返回事件的类型 比如 click mouseover 不带on

e.cancelBubble

该属性阻止冒泡   非标准  ie6-8使用

e.returnValue

该属性 阻止默认事件(默认行为) 非标准  ie6-8使用  比如不让链接跳转

e.preventDefault()

阻止默认事件(默认行为) 标准  比如不让链接跳转

e.stopPropagation() 

阻止冒泡   标准

 代码示例:

<body>
  <div>123</div>
  <ul>
    <li>asd1</li>
    <li>asd2</li>
    <li>asd3</li>
  </ul>
  <script>
    // 常见的事件对象的属性和方法
    // e.target  返回触发事件的对象(元素)  标准  this 返回的是绑定事件的对象(元素)
    var div = document.querySelector('div');
    div.addEventListener('click', function (e) {
      console.log(e.target);
      console.log(this);
    })
    var ul = document.querySelector('ul');
    ul.addEventListener('click', function (e) {
      // 我们个给ul绑定事件 那么 this 就指向 ul
      console.log(this, e.currentTarget) // ul 
      //  e.currentTarget  和 this 是相同的,但是 e.currentTarget ie678不认识
      console.log(e.currentTarget === this);// true
      // e.target 指向我们点击的那个对象
      console.log(e.target) //li
    })
  </script>
</body>

14.3 事件对象阻止默认行为

<body>
  <div>123</div>
  <a href="http://www.baidu.com">百度</a>
  <form action="http://www.baidu.com">
    <input type="submit" value="提交" name="sub">
  </form>
  <script>
    // 常见事件对象的属性和方法
    // 1.返回事件类型
    var div = document.querySelector('div')
    var a = document.querySelector('a')
    div.addEventListener('click', fn)
    div.addEventListener('mouseover', fn)//鼠标经过
    div.addEventListener('mouseout', fn)//鼠标离开
    function fn(e) {
      console.log(e.type)
    }
    // 2.阻止默认行为(事件) 让链接不跳转  或者让 提交按钮不提交
    a.onclick = function (e) {
      // e.preventDefault()  //标准
      // ie 678 才识别  e.returnValue  
      // e.returnValue //

      /* 我们也可以利用return false 也能阻止默认行为 特点:return false 后面的代码不会被执行
      而且只限于传统的注册方式 */
      return false
      alert(11)
    }
  </script>
</body>

14.4 阻止事件冒泡

方式:

  • e.stopPropagation()  DOM 推荐的标准方式
  • e.cancelBubble  该属性阻止冒泡   非标准  ie6-8使用  
  • e.cancelBubble = true

 代码示例:

<style>
  .father {
    position: relative;
    width: 200px;
    height: 200px;
    background-color: pink;
    margin: 100px auto;
  }

  .father .son {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 100px;
    height: 100px;
    background-color: purple;
    text-align: center;
    line-height: 100px;
  }
</style>

<body>
  <div class="father">
    <div class="son">son盒子</div>
  </div>
  <script>
    // 阻止冒泡  dom 推荐的标准 e.stopPropagation();
    var son = document.querySelector('.son');
    son.addEventListener('click', function (e) {
      alert('son');// 点击son时冒泡阶段 先执行 son 再到 father
      // 过程: son(目标)->father ->body ->html-> document 
      //    兼容性方案
      if (e && e.stopPropagation) {
        e.stopPropagation();
      } else {
        window.event.cancelBubble = true;
      }
    }, false);
    var father = document.querySelector('.father');
    father.addEventListener('click', function () {
      alert('father');
    }, false);
        // 5.实际开发中我们很少使用使用事件捕获,我们更关注事件冒泡
        // 6.有些事件没有冒泡,比如onblur、onfocus、onmouseenter、onmouseleave
        // onblur 失去鼠标焦点触发  onfocus 获取鼠标焦点触发

  </script>
</body>

14.5 事件委托

事件委托的原理: 不是每一个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响每个子节点

代码示例:

<bnody>
  <!-- 
    以下案例:给ul注册点击事件,然后利用事件对象的target来找到当前点击的li,因为点击li,
            事件会冒泡到ul上,ul有注册事件,就会触发事件监听器
    事件委托的作用:我们只操作了一次DOM,提高了程序的性能 
-->
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
    <li>10</li>
  </ul>
  <script>
    var ul = document.querySelector('ul')
    var li = document.querySelectorAll('li')
    ul.addEventListener('click', fn) // 给 ul 节点绑定事件,但是你点击 li 节点,事件一样会触发
    function fn(e) {
      // 利用排他思想先清空其他节点的背景色
      for (var i = 0; i < li.length; i++) {
        li[i].style.backgroundColor = '';
      }
      console.log(e.target) // e.target 返回触发事件的对象  标准
      // 使用 e.target 事件属性才能准确捕捉到当前点击的节点
      e.target.style.backgroundColor = 'pink'
      alert('知否知否,点我应有弹框在手!')
    }
  </script>
</bnody>

14.6 鼠标事件对象

介绍:

event对象代表事件的状态,跟事件相关的一系列星系的集合,包括了鼠标事件对象、键盘事件对象等

鼠标事件对象

说明

e.clientX

返回鼠标相对于浏览器窗口可视区X坐标

e.clientY

返回鼠标相对于浏览器窗口可视区Y坐标

e.pageX

返回鼠标相对于文档页面的X坐标

e.pageY 

返回鼠标相对于文档页面的Y坐标

e.screenX

返回鼠标相对于电脑屏幕的X坐标

e.screenY

返回鼠标相对于电脑屏幕的Y坐标

代码示例:

<style>
  body {
      height: 2000px;
  }
</style>
<body>
    <script>
        // 鼠标事件对象 MouseEvent 
        document.addEventListener('click', function (e) {
            // 返回鼠标相对于浏览器窗口可视区坐标
            console.log(e.clientX);
            console.log(e.clientY);
            console.log('---------------------------------------------------------------------------------------------------------');
            // 返回鼠标相对于文档页面的坐标
            console.log(e.pageX);
            console.log(e.pageY);
            console.log('---------------------------------------------------------------------------------------------------------');
            // 返回鼠标相对于电脑屏幕的坐标
            console.log(e.screenX);
            console.log(e.screenY);
        })
    </script>
</body>

15、键盘事件

键盘事件触发条件
onkeyup        某个按键松开时 触发
onkeydown      某个按键按下时 触发
onkeypress     某个按键按下时 触发  但是它不识别功能键

代码示例

<body>
  <script>
    // 常用的键盘事件
    // 1.keyup 按键弹起的时候触发
    // document.onkeyup = function () {
    //     console.log('我键盘弹起时触发');
    // }
    document.addEventListener('keydown', function () {
      console.log('我键盘按下时触发');
    })


    document.onkeypress = function () {
      console.log('我键盘按下时触发,不识别功能键');
    }
        // 三个事件的执行顺序 keydown->keypress->keyup
  </script>
</body>

     键盘事件对象中的 keyCode 属性可以得到相应的ASCII码值

    案例:判断用户按下那个键

<body>
    <script>
        // 1.键盘事件对象中的keyCode属性可以得到相应的ASCII码值
        // 2.onkeyup  某个按键松开触发   onkeydown某个按键按下时触发 事件 它们不区分字母大小写
        // 3.onkeypress某个按键按下时触发但是它不识别功能键 它区分字母大小写
        document.addEventListener('keyup', function (e) {
            console.log('不区分大小写keyup:' + e.keyCode);//A 
            if (e.keyCode === 65) {
                alert('您按下了a键')
            } else {
                alert('您没有按下了a键')
            }
        })

        // 三个事件的执行顺序 keydown->keypress->keyup
        document.addEventListener('keypress', function (e) {
            console.log('我区分大小写press:' + e.keyCode);

        })
    </script>
</body>

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
以下是一些可能会出现在Web前端开发中级考试中的理论题以及对应的答案: 1. 请简要解释一下什么是 MVC 架构? MVC 架构是一种软件设计模式,它将一个应用程序分为三个部分:模型(Model)、视图(View)和控制器(Controller)。模型负责处理数据和业务逻辑,视图负责将数据呈现给用户,控制器负责协调模型和视图之间的交互。 2. 请简单介绍一下HTML5新特性。 HTML5是HTML的最新版本,它引入了很多新的特性,例如:语义化标签、视频和音频支持、地理定位、Web存储、Web Workers等。 3. 请列举一些CSS3中新增的特性。 CSS3引入了很多新的特性,例如:圆角、阴影、渐变、动画、多列布局、媒体查询等。 4. 请简要说明JavaScript中的几种数据类型。 JavaScript中的数据类型包括:基本类型和引用类型。基本类型包括:字符串、数字、布尔值、undefined和null。引用类型包括:对象、数组、函数等。 5. 请简述 Ajax 的工作原理。 Ajax的工作原理是通过XMLHttpRequest对象向服务器异步发送请求,获取服务器返回的数据,然后通过JavaScript动态更新页面内容,从而实现局部刷新,提高用户体验。 6. 请简单介绍一下 HTTP 协议的几个常见方法。 HTTP协议定义了很多请求方法,其中常见的有:GET、POST、PUT、DELETE、HEAD等。GET用于获取资源,POST用于提交数据,PUT用于更新资源,DELETE用于删除资源,HEAD用于获取资源的元数据。 7. 请简述一下浏览器缓存的工作原理。 浏览器缓存是指浏览器将已经获取的资源存储在本地,下次访问同一资源时直接从本地获取,从而提高访问速度和用户体验。浏览器缓存的工作原理是通过HTTP协议中的响应头来控制缓存行为,例如:Cache-Control、Expires、Last-Modified、ETag等。 8. 请简单介绍一下 Web 安全相关的知识。 Web安全涉及到很多方面,包括:XSS攻击、CSRF攻击、SQL注入、文件上传漏洞、密码安全等。开发者需要采取一系列措施来保障Web应用的安全,例如:输入验证、输出转义、密码加密、HTTPS协议等。 9. 请简述一下前端性能优化的几个方面。 前端性能优化可以从多个方面入手,例如:减少HTTP请求、压缩和合并JavaScript和CSS文件、优化图片、使用CDN、减少DOM操作、使用缓存等。 10. 请简述一下现代前端框架的特点和优势。 现代前端框架的特点和优势包括:提供了一整套解决方案,可以快速构建Web应用;采用组件化的开发方式,可以提高代码的可重用性和可维护性;提供了丰富的工具和插件,可以提高开发效率和代码质量;支持自动化构建和测试,可以提高开发效率和代码质量。常见的现代前端框架包括:React、Vue、Angular等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

狗蛋的博客之旅

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值