一、概念

1、简介

Document Object Model ,DOM,文档对象模型,是编程接口

通过这些接口可以改变网页的内容、结构和样式

2、DOM 树

  ① 文档:一个页面就是一个文档,DOM 中使用 document 表示

  ② 元素:页面中的所有标签都是元素,DOM 中使用 element 表示

  ③ 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node 表示

DOM 把以上内容都看作是对象 Object 类型

二、获取元素

1、获取普通元素

(1)getElementById 方法

<body>
    <div id="time">2019-9-9</div>
    <script>
        var timer = document.getElementById('time');
        console.log(timer);         //<div id="time">2019-9-9</div>   获取到id为timer的元素
        console.log(typeof timer);  //object   页面内的文档、元素、节点等都是对象类型
        console.dir(timer);         //div#time    dir()能查看元素对象的属性和方法
    </script>
</body>

(2)getElementsByTagName 方法

<body>
    <ul>
        <li>知否知否1</li>
        <li>知否知否2</li>
        <li>知否知否3</li>
        <li>知否知否4</li>
        <li>知否知否5</li>
    </ul>
    <script>
        var lis = document.getElementsByTagName('li');
        console.log(lis);        //HTMLCollection(5) [li, li, li, li, li]  获取以伪数组存储的元素对象
        console.log(typeof lis); //object
        console.log(lis[0]);     //<li>知否知否1</li>   类似数组获取元素、遍历元素
    </script>
</body>

如果页面内只有一个或者没有这个 TagName,获取到的也是伪数组的形式

还可以获取某个指定元素下的子元素,如下:

<body>
    <ul>
        <li>知否知否1</li>
        <li>知否知否2</li>
    </ul>
    <ol id="ol">
        <li>应是绿肥红瘦1</li>
        <li>应是绿肥红瘦2</li>
    </ol>
    <script>
   //获取ol下的li,不要ul下的li
        //1.先通过getElementById获取指定元素
        var ol = document.getElementById('ol'); 

        //2.再通过getElementsByTagName获取指定元素的子元素
        var olLi = ol.getElementsByTagName('li'); 
        console.log(olLi);   //HTMLCollection(2) 以伪数组形式存储的元素对象
    </script>
</body>

(3)getElementsByClassName 方法

<body>
    <div class="box">box1</div>
    <div class="box">box2</div>
    <script>
        var boxs = document.getElementsByClassName('box');
        console.log(boxs);  //HTMLCollection(2)
    </script>
</body>

(4)querySelecter 方法

  • H5 新增获取元素的方法
  • 只能获取第一个元素
  • 不同选择器需要加符号来区分
<body>
    <div class="box">box1</div>
    <div class="box">box2</div>
    <div id="nav">
        <ul>
            <li>首页</li>
            <li>产品</li>
        </ul>
    </div>
    <script>
        var boxOne = document.querySelector('.box'); // class选择器用 .
        console.log(boxOne);   //<div class="box">box1</div> 只能获取第一个元素
        var nav = document.querySelector('#nav');    // id选择器用 #
        console.log(nav);  
        var liOne = document.querySelector('li');    // 标签选择器
        console.log(liOne); 
    </script>
</body>

(5)querySelecterAll 方法

  • H5 新增获取元素的方法
  • 能获取所有元素
  • 不同选择器需要加符号来区分
<body>
    <div class="box">box1</div>
    <div class="box">box2</div>
    <div id="nav">
        <ul>
            <li>首页</li>
            <li>产品</li>
        </ul>
    </div>
    <script>
        var boxOne = document.querySelectorAll('.box'); // class选择器用 .
        console.log(boxOne);   //NodeList(2) 获取所有元素
        var nav = document.querySelectorAll('#nav');    // id选择器用 #
        console.log(nav);  
        var liOne = document.querySelectorAll('li');    //标签选择器
        console.log(liOne); 
    </script>
</body>

2、获取特殊元素

(1)获取 body 元素

<body>
    <script>
        var bodyEle = document.body;
        console.log(bodyEle);
    </script>
</body>

(2)获取 html 元素

<body>
    <script>
        var htmlEle = document.documentElement;
        console.log(htmlEle);
    </script>
</body>

三、事件基础

1、事件三要素

  ① 事件源,例如:按钮

  ② 事件类型,例如:点击、经过、键盘按下等

  ③ 事件处理程序,例如:弹出对话框

2、执行事件步骤

  ① 获取事件源

  ② 注册事件

  ③ 添加事件处理程序

<body>
    <!-- 点击div,控制台输出我被选中了 -->
    <div id="btn">盒子</div>
    <script>
        //1.获取事件源
        var btn = document.getElementById('btn')  //获取元素
        //2.注册事件----元素.事件
        //btn.onclick    
        //3.添加事件处理程序----匿名函数赋值
        btn.onclick = function() {    
            console.log('我被选中了!');
        }
    </script>
</body>

四、操作元素

1、修改元素包含的内容

(1)innerText 属性

<body>
    <button>显示时间</button>
    <div>某个时间</div>
    <script>
        //点击button后,div 中的文字变为时间
        var btn = document.querySelector('button');
        var div = document.querySelector('div');
        btn.onclick = function() {
            div.innerText = '2022-04-05';  // innerText 是属性,用等号赋值
        }
    </script>
</body>

(2)innerHTML 属性

<body>
    <div id="div1"></div>
    <div id="div2"></div>
    <script>
        var divEle1 = document.querySelector('#div1');
        var divEle2 = document.querySelector('#div2');
        divEle1.innerHTML = '我是一个盒子';
        divEle2.innerHTML = '<strong>我是</strong>第二个盒子';  //能识别html标签
    </script>
</body>

innerText 和 innerHTML 区别:

  • innerText:不识别 html 标签;去除空格和换行
  • innerHTML:识别 html 标签;保留空格和换行

注意:修改表单元素中的内容和普通元素不同:

  • 普通元素通过修改 innerHTML 和 innerText 属性
  • 表单元素要修改 value 属性,尤其是

2、修改元素的属性

给属性重新赋值即可,案例:

<body>
    <button id="btn1">有道词典</button>
    <img src="img/music.png"/>
    <script>
        //点击button,图片切换为QQ音乐
        var youdao = document.querySelector('#btn1');
        var img = document.querySelector('img');
        youdao.onclick = function() {
            img.src = 'img/youdao.png';  //修改img元素的src属性,直接给src重新赋值即可
        }
    </script>
</body>

3、修改元素的样式属性

(1)通过 style 修改

<script>
    var div = document.querySelector('div');
    div.onclick = function () {
        div.style.width = '500px';            // 元素名.style.样式属性名
        div.style.backgroundColor = 'blue'; // html是-,JS是驼峰   
    }
</script>

注意:JS 修改 style 样式属性,产生的是行内样式

(2)通过 className 修改

<div class="box"></div>
<script type="text/javascript">
    var box = document.querySelector('div');
    box.onclick = function() {             //1.元素名.className 来操作元素类名属性
        this.className = 'box boxChange';  //2.这样修改样式属性会直接覆盖之前的类名,可以用多类名来解决
    }                                      //3.当修改样式较多时,可以使用className来修改
</script>

4、排他思想

如果有一组元素,想要某个元素实现某种样式,需要用到循环的排他算法

<script type="text/javascript">
    var btns = document.getElementsByTagName('button');
    //通过循环给所有按钮添加onclick点击事件
    for (var i = 0; i < btns.length; i++) { 
        btns[i].onclick = function() {
            //1.先把所有元素清除样式
            for (var j = 0; j < btns.length; j++) {
                btns[j].style.backgroundColor = '';    
            }
            //2.再给某个元素设置想要的样式
            this.style.backgroundColor = 'pink';   //这里不能用btn[i] 不是同一个作用域 i不起作用
        }
    }
</script>

5、操作元素的自定义属性

<div index="1" test="test"></div>
<script type="text/javascript">
    var div = document.querySelector('div');
    //1.获得自定义属性值 getAttribute
    console.log(div.getAttribute('index'));  //1
    //2.设置自定义属性值 setAttribute
    div.setAttribute('index','2');
    console.log(div.getAttribute('index'));  //2
    //3.移除自定义属性值 removeAttribute
    div.removeAttribute('test');
</script>

6、H5 自定义属性

自定义属性目的:为了保存并使用数据,有些数据不用保存到数据库,保存在页面中就可以了

但是自定义属性难以判断,所以 H5 新增了自定义属性命名方式:

  • data-xxx 

获取自定义属性值:

  • 元素.dataset.xxx 
<div data-time = "21时" data-index = "22" data-list-name = "andy"></div>
<script type="text/javascript">
    var div = document.querySelector('div');
    //dataset 是一个集合,里面存放了所有以 data 开头的自定义属性
    console.log(div.dataset);         //DOMStringMap {time: '21时', index: '22'}
    console.log(div.dataset.time);    //获取自定义属性 只能获取data-开头的
    console.log(div.dataset.listName); // 驼峰命名法
    console.log(div.dataset['time']);
</script>

 五、操作节点

1、节点概述

网页中的所有内容都是节点(标签、属性、文本、注释等)

每种节点都至少拥有 nodeType(节点类型)、nodeName(节点名称)、nodeValue(节点值)这三个基本属性

  • 元素节点 nodeType = 1
  • 属性节点 nodeType = 2
  • 文本节点 nodeType = 3 (文本节点包含文字、空格、换行等)

实际操作中,主要操作的是元素节点

2、节点层级

(1)父节点

  • 获取父节点
node.parentNode

注意:

  ① 返回的是最近的父节点

  ② 没有父节点返回 null

(2)子节点

  • 获取所有子节点
// 方法一:返回所有的子节点,包含元素节点、文本节点等(不常用)
node.childNodes
// 方法二:返回子节点中的元素节点(常用) 
node.children
  • 获取第一个子节点
// 方法一:返回第一个子节点,包含元素节点、文本节点等(不常用)
node.firstChild
// 方法二:返回子节点中的第一个元素节点 (IE9 以上才支持)
node.firstElementChild
// 方法三:返回子节点中的第一个元素节点(常用)
node.children[0]
  • 获取最后一个子节点
// 方法一:返回最后一个子节点,包含元素节点、文本节点等(不常用)
node.lastChild
// 方法二:返回子节点中的最后一个元素节点 (IE9 以上才支持)
node.lastElementChild
// 方法三:返回子节点中的最后一个元素节点 (常用)
node.children[children.length - 1]

(3)兄弟节点(不常用)

  • 获取上一个兄弟节点
// 方法一:返回上一个兄弟节点,包含元素节点、文本节点等(IE9 以上才支持)
node.previousSibling
// 方法二:返回兄弟节点中上一个元素节点(IE9 以上才支持)
node.previousElementSibling
  • 获取下一个兄弟节点
// 方法一:返回下一个兄弟节点,包含元素节点、文本节点等(IE9 以上才支持)
node.nextSibling
// 方法二:返回兄弟节点中下一个元素节点(IE9 以上才支持)
node.nextElementSibling

(4)创建、添加子节点

<ul>
    <li>123</li>
</ul>
<script type="text/javascript">
    var ul = document.querySelector('ul');
    // 1.创建元素节点
    var li1 = document.createElement('li');
    var li2 = document.createElement('li');
    // 2.添加节点
    // (1)在后面追加
    ul.appendChild(li1);  
    // (2)在前面添加
    ul.insertBefore(li2, ul.children[0]);
</script>

(5)删除子节点

<ul>
    <li>1</li>
    <li>2</li>
</ul>
<script type="text/javascript">
    var ul = document.querySelector('ul');
    ul.removeChild(ul.children[0]); //会把内容为1的子节点删除掉
</script>

(6)复制节点

<ul>
    <li>1</li>
</ul>
<script type="text/javascript">
    var ul = document.querySelector('ul');
    // 1.括号为空或 false 为浅拷贝,只复制标签不复制内容
    var li1 = ul.children[0].cloneNode();
    // 2.括号为 true 为深拷贝,标签和内容都复制
    var li2 = ul.children[0].cloneNode(true);
    ul.appendChild(li1);
    ul.appendChild(li2);
</script>

(7)三种动态创建元素区别

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

六、注册事件

1、概述

给元素添加事件,称为注册事件或绑定事件;

2、注册事件

(1)传统方式注册事件

同一个元素、多次注册同一个事件,只有一个生效,具有唯一性

(2)方法监听注册事件

同一个元素、多次注册同一个事件,都生效,不具有唯一性

IE9 以上才支持

<button type="button">事件侦听注册事件</button>
<script type="text/javascript">
    var btn = document.querySelector('button');
    btn.addEventListener('click', function() {  //第一个参数是事件类型字符串:加引号、不带on
        alert('点击了事件侦听按钮!');             //第二个参数是事件处理程序函数
    })
</script>

3、删除事件

(1)传统方式注册的事件

<script type="text/javascript">
    var div = document.querySelector('div');
    div.onclick = function() {
        alert('要开心呀!!!');
        div.onclick = null;  //传统方式删除事件
    }
</script>

(2)方法监听注册的事件

<script type="text/javascript">
    var div = document.querySelector('div');
    div.addEventListener('click', fn);         // 不用加小括号()
    function fn(){
        alert('一定要开心!');
        div.removeEventListener('click',fn);   // 方法监听注册事件删除事件
    }
</script>

七、DOM 事件流

  • DOM 事件流描述的是从页面接收事件的顺序
  • 捕获阶段当前目标阶段冒泡阶段
  • JS 代码中只能执行捕获或冒泡其中的一个阶段
  • onclick 、attachEvent 只能得到冒泡阶段
  • addEventListener 第三个参数是 true,表示在事件捕获阶段调用事件处理程序;如果是 false 或省略,表示在事件冒泡阶段调用事件处理程序
  • 实际开发中很少使用事件捕获,我们更关注事件冒泡 
  • 有些事件是没有冒泡的,比如 onblur、onfocus

八、事件委托

1、概念

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

2、原理

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

九、事件对象

  • 事件对象是事件的一系列相关数据的集合,比如鼠标点击事件是鼠标事件对象(如鼠标坐标等)、键盘事件是键盘事件对象(如判断用户按下了哪个键等)
  • 事件对象在事件处理程序函数的小括号里,当形参来看
  • 事件对象只有有了事件才会存在,是系统给我们自动创建的,不需要我们传递参数
  • 事件对象可以自己命名,比如:event、evt、e等
  • 事件对象也有兼容性,ie678 通过 window.event 兼容性写法 e = e || window.event
  • 事件对象的常见属性和方法:
  • e.target 返回触发事件的对象(而 this 返回的是调用事件的对象,两者只在某些情况下结果相同)
  • e.type 返回事件的类型,比如 click、mouseover(不带 on)
  • e.preventDefault() 阻止默认事件的方法,比如让链接不跳转、让提交按钮不提交
  • e.returnValue 阻止默认事件的属性,ie678使用
  • 阻止事件冒泡:
  • e.stopPropagation() 方法
  • e.cancelBubble 属性

十、常用的鼠标事件

1、禁止右键菜单 contextmenu

<p>禁止右键菜单</p>
<script type="text/javascript">
    var p = document.querySelector('p');
    p.addEventListener('contextmenu', function(e) {
        e.preventDefault();
    })
</script>

绑定 contextmenu 事件后,用阻止默认事件的方法 e.preventDefault() 禁止掉就可以了

2、禁止选中文字 selectstart

<p>禁止选中文字</p>
<script type="text/javascript">
    var p = document.querySelector('p');
    p.addEventListener('selectstart', function(e) {
        e.preventDefault();
    })
</script>

绑定 selectstart 事件后,用阻止默认事件的方法 e.preventDefault() 禁止掉就可以了

3、鼠标事件对象的属性

e.clientX 鼠标在可视区的 x 坐标

e.clientY 鼠标在可视区的 y 坐标

e.pageX 鼠标在页面文档的 x 坐标

e.pageY 鼠标在页面文档的 y 坐标

4、鼠标移动事件 mousemove

跟随鼠标的天使案例:

<head>
    <meta charset="utf-8">
    <title></title>
    <style type="text/css">
        img {
            position: absolute;    /* 图片要移动 而且不占位置 -> 绝对定位 absolute */
        }
    </style>
</head>
<body>
    <img src="img/angel.gif" alt="">
    <script>
        var pic = document.querySelector('img');
        document.addEventListener('mousemove', function(e) {  //只要鼠标移动 1px 就会触发事件
            var x = e.pageX;
            var y = e.pageY;
            pic.style.left = x + 'px'; // left 和 top 不要忘记单位px 
            pic.style.top = y + 'px';
        }) 
    </script>
</body>

十一、常用的键盘事件

1、按键弹起 keyup

  • 弹起才触发
<script type="text/javascript">
    document.addEventListener('keyup', function() {
        console.log('弹起');
    })
</script>

2、按键按下 keydown

  • 只要按下不松开就一直触发
  • keydown 能识别功能键,如:ctrl、shift、箭头等
  • 相同情况下 keydown 比 keypress 先执行
<script type="text/javascript">
    document.addEventListener('keydown', function() {
        console.log('按下');
    })
</script>

3、按键按下 keypress

  • 只要按下不松开就一直触发
  • keypress 不识别功能键
<script type="text/javascript">
    document.addEventListener('keypress', function() {
        console.log('按下');
    })
</script>

4、键盘事件对象的属性

e.keycode 相应键的 ASCII 码

  • keyup 事件和 keydown 事件的 keycode 属性不区分大小写
  • keypress 事件的 keycode 属性区分大小写

 

Posted on 2022-03-10 16:18  choco莉特  阅读(22)  评论(0编辑  收藏  举报