DOM事件基础知识

1. DOM 简介

1.1 什么是 DOM

在这里插入图片描述

1.1 DOM 树

在这里插入图片描述
DOM 把以上内容都看做是对象

2. 获取元素

2.1 如何获取元素
  • 根据 ID 获取
  • 根据标签名获取
  • 通过 HTML5 新增的方法获取
  • 特殊元素获取
2.2 根据 ID 获取

使用 getElementById() 方法可以获取带有 ID 的元素对象
在这里插入图片描述

2.3 根据标签名获取

使用 getElementsByTagName() 方法可以返回带有指定标签名的对象的集合
在这里插入图片描述
还可以获取某个元素(父元素)内部所有指定标签名的子元素

element.getElementsByTagNmae('标签名');

注意:父元素必须是单个对象(必须指明哪一个元素对象).获取的时候不包括父元素自己

2.4 通过 HTML5 新增的方法获取
1. document.getElementsByClassName('类名');//根据类名返回元素对象集合
//这个包括前几种不需要加 . # 等符号
2. document.querySelector('选择器');//根据指定选择器返回第一个元素对象
//需要加符号
3. document.querySelectorAll('选择器');//根据指定选择器返回所有符合的
2.5 获取特俗元素( body ,html )

获取body元素

1. document.body // 返回body元素对象
2. document.documentElement// 返回html元素对象

3. 事件基础

3.1 事件概述

JavaScript使我们有能力创建动态页面,而事件是可以被JavaScript侦测到的行为。
简单理解:触发响应机制

案例理解
在这里插入图片描述

3.2 执行事件的步骤
  1. 获取事件源
  2. 注册事件( 绑定事件 )
  3. 添加事件处理程序(采取函数赋值形式)

案例理解
在这里插入图片描述

3.3 常见的鼠标事件

在这里插入图片描述

4. 操作元素

JavaScript 的 Dom 操作可以改变网页内容、结构和样式,我们可以利用 Dom 操作元素来改变元素里面的内容、属性等。注意以下都是属性

4.1 改变元素内容
element.innerText // element 是元素

获取内容,也可修改内容,不识别html标签(修改时不运行html代码),完全打印文本,同时原本的空格和换行也会去掉

element.innerHTML

获取内容修改内容,识别html标签(修改时会进行html代码操作),同时保留原本的空格和换行

案例理解
<button>显示当前系统事件</button>
<div>某个时间</div>
<p>1111</p>
<script>
	// 当我们点击了按钮, div里面的文字会发生变化
	// 1. 获取元素
	var btn = document.querySelector('button');
	var div = document.querySelector('div');
	// 2.注册事件
	btn.onclick = function(){
		div.innerText = getDate();
	}    
	
	function getDate(){
		var date = new Date();
		var year = date.getFullYear();
		var month = date.getMonth() + 1; //索引是 0-11 所以要加1
		var dates = date.getDate();
		var arr = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'];
		var day = date.getDay();
		return '今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day];
	}
	
	// 我们元素可以不用添加事件
	var p = document.querySelector('p');
	p.innerText = getDate();
	
</script>
4.2 改变元素内容
1. innerText、innerHTML 改变元素内容
2. src、href
3. id、alt、title

案例理解
在这里插入图片描述

4.3 表单元素的属性操作

利用 DOM 可以操作如下表单元素的属性:

type、value、checked、selected、disabled

案例理解
<button>按钮</button>
<input type="text" name="" id="" value="输入内容">
<script>
    // 1.获取元素
    var btn = document.querySelector('button');
    var input = document.querySelector('input');
    // 2.注册事件 处理程序
    btn.onclick = function(){
        // input.innerHTML = '点击了' 这个是普通盒子 比如 div 标签里面的内容
        // 表单里面的值 文字内容是通过 value 来修改的
        input.value = '被点击了';
        // 如果想要某个表单被禁 不能再点击 disabled 我们想要这个按钮 button 禁用
        // btn.disabled = true;
        this.disabled = true;
        // this 指向的是事件函数的调用者
    }
</script>
仿京东显示隐藏密码案例
<style>
    .box {
        position: relative;
        width: 400px;
        border-bottom: 1px solid #ccc;
        margin: 100px auto;
    }
    .box input {
        width: 370px;
        height: 30px;
        border: 0;
        outline: none;
    }
    .box img {
        position: absolute;
        top: 4px;
        right: 2px;
        width: 24px;
    }
</style>
</head>
<body>
	<div class="box">
	    <label for="">
	        <img src="img/eyeclose.png" alt="" id="eye">
	    </label>
	    <input type="password" name="" id="pwd">
	</div>
	<script>
	    // 1. 获取元素
	    var eye = document.getElementById('eye');
	    var pwd = document.getElementById('pwd');
	    // 2.注册事件  处理程序
	    var flag = 0;
	    eye.onclick = function(){
	        // 点击一次之后  flag 一定要变化
	        if(flag == 0){
	            pwd.type = 'text';
	            eye.src = 'img/eyeopen.png';
	            flag = 1;
	        }else{
	            pwd.type = 'password';
	            eye.src = 'img/eyeclose.png';
	            flag = 0;
	        }
	        
	    }
	</script>
</body>
4.4 样式属性操作

我们可以通过 JS 修改元素的大小、颜色、位置等样式。

1. element.style      行内样式操作
2. element.className  类名样式操作

注意:

  1. JS 里面的样式采取驼峰命名法 比如 fontSize,backgroundColor
  2. JS 修改 style 样式操作,产生的是行内样式,css权重比较高
获取和失去焦点案例
	<style>
        input{
            color: #999;
        }
    </style>
</head>
<body>
    <input type="text" name="" id="" value = "手机">
    <script>
        var text = document.querySelector('input');
        // 2. 注册事件   获取焦点事件  onfocus
        text.onfocus = function(){
            console.log('得到了焦点');
            if(this.value === '手机'){
                this.value = '';
            }
            // 获得焦点需要把文本框里面的文字变黑
            this.style.color = '#333';
        } 
        // 3. 注册事件   失去焦点事件  onblur
        text.onblur = function(){
            console.log('失去了焦点');
            if(this.value === ''){
                this.value = '手机';
            }
            this.style.color = '#999';
        }
    </script>
</body>
利用 className 修改样式案例
	<style>
        div{
            width: 100px;
            height: 100px;
            background-color: pink;
        }
        .change{
            background-color: purple;
            color: #fff;
            font-size: 25px;
            margin-top: 100px;
        }
    </style>
</head>
<body>
    <div class='first'>文本</div>
    <script>
        // 1. element.style  样式少或功能简单才使用
        var text = document.querySelector('div');
        text.onclick = function(){
        	//若想保留原先类名,前面添加即可
            this.className = 'first change';
        }
    </script>
</body>
仿新浪注册页面
	<style>
        div{
            width: 600px;
            margin: 100px auto;
        }
        .message {
            display: inline-block;
            font-size: 12px;
            color: #999;
            /* background: url(img/mess.png) no-repeat left center; */
            padding-left: 20px;
        }
        .wrong {
            color: red;
            background: url(img/wrong.png);
        }
        .right {
            color: green;
            background: url(img/right.png);
        }
    </style>
</head>
<body>
    <div class="register">
        <input type="password" class="ipt">
        <p class="message">请输入6~16位密码</p>
    </div>
    <script>
        // 首先判断的事件是表单失去焦点 onblur
        var ipt = document.querySelector('.ipt');
        var message = document.querySelector('.message');
        ipt.onblur = function(){
            //根据表单里面值的长度  ipt.value.length
            if(this.value.length < 6 || this.value.length > 16){
                console.log('错误');
                message.className = 'message wrong'
                message.innerHTML = '您需要输入6~16位数字';
            }else{
                message.className = 'message right'
                message.innerHTML = '您输入正确';
            }
        }
    </script>
</body>
4.5 操作元素总结

在这里插入图片描述

4.6 排他思想

首先排除其他人,然后才设置自己的样式,这种排除其他人的思想我们称为排他思想。

案例
<body>
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <button>按钮4</button>
    <button>按钮5</button>
    <script>
        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>
全选反选案例(重要)
<style>
        * {
            padding: 0;
            margin: 0;
        }
        
        .wrap {
            width: 300px;
            margin: 100px auto 0;
        }
        
        table {
            border-collapse: collapse;
            border-spacing: 0;
            border: 1px solid #c0c0c0;
            width: 300px;
        }
        
        th,
        td {
            border: 1px solid #d0d0d0;
            color: #404060;
            padding: 10px;
        }
        
        th {
            background-color: #09c;
            font: bold 16px "微软雅黑";
            color: #fff;
        }
        
        td {
            font: 14px "微软雅黑";
        }
        
        tbody tr {
            background-color: #f0f0f0;
        }
        
        tbody tr:hover {
            cursor: pointer;
            background-color: #fafafa;
        }
    </style>
</head>
<body>
    <div class="wrap">
        <table>
            <thead>
                <tr>
                    <th>
                        <input type="checkbox" id="j_cbAll" />
                    </th>
                    <th>商品</th>
                    <th>价钱</th>
                </tr>
            </thead>
            <tbody id="j_tb">
                <tr>
                    <td>
                        <input type="checkbox" />
                    </td>
                    <td>iPhone8</td>
                    <td>8000</td>
                </tr>
                <tr>
                    <td>
                        <input type="checkbox" />
                    </td>
                    <td>iPad Pro</td>
                    <td>5000</td>
                </tr>
                <tr>
                    <td>
                        <input type="checkbox" />
                    </td>
                    <td>iPad Air</td>
                    <td>2000</td>
                </tr>
                <tr>
                    <td>
                        <input type="checkbox" />
                    </td>
                    <td>Apple Watch</td>
                    <td>2000</td>
                </tr>
            </tbody>
        </table>
    </div>
    <script>
        // 1. 全选和取消全选做法:  让下面所有复选框的checked属性(选中状态) 跟随 全选按钮即可
        // 获取元素
        var j_cbAll = document.getElementById('j_cbAll'); // 全选按钮
        var j_tbs = document.getElementById('j_tb').getElementsByTagName('input'); // 下面所有的复选框
        // 注册事件
        j_cbAll.onclick = function() {
        	// this.checked 它可以得到当前复选框的选中状态如果是true 就是选中,如果是false 就是未选中
            console.log(this.checked);
            for (var i = 0; i < j_tbs.length; i++) {
                j_tbs[i].checked = this.checked;
            }
        }
        // 2. 下面复选框需要全部选中, 上面全选才能选中做法: 给下面所有复选框绑定点击事件,每次点击,都要循环查看下面所有的复选框是否有没选中的,如果有一个没选中的, 上面全选就不选中。
        for (var i = 0; i < j_tbs.length; i++) {
            j_tbs[i].onclick = function() {
                // flag 控制全选按钮是否选中
                var flag = true;
                // 每次点击下面的复选框都要循环检查者4个小按钮是否全被选中
                for (var i = 0; i < j_tbs.length; i++) {
                    if (!j_tbs[i].checked) {
                        flag = false;
                        break; // 退出for循环 这样可以提高执行效率 因为只要有一个没有选中,剩下的就无需循环判断了
                    }
                }
                j_cbAll.checked = flag;
            }
        }
    </script>
</body>
4.7 自定义属性的操作
1. 获取属性值
  • element.属性 获取属性值
  • element.getAttribute(’ 属性 ');

区别:

  • element.属性 获取内置属性值(元素本身自带的属性 class id 等)
  • element.getAttribute(’ 属性 '); 主要获取自定义的属性(标准)我们程序员自定义添加的属性
2. 设置元素属性值
  • element.属性 = ‘值’ 设置内置属性值
  • element.setAttribute( ‘属性’ ,‘值’ ); 主要针对自定义属性(标准)
3. 移除属性
  • element.removeAttribute( ‘属性’ );
tab栏切换案例(重要)
<body>
    <div class="tab">
        <div class="tab_list">
            <ul>
                <li class="current">商品介绍</li>
                <li>规格与包装</li>
                <li>售后保障</li>
                <li>商品评价(50000</li>
                <li>手机社区</li>
            </ul>
        </div>
        <div class="tab_con">
            <div class="item" style="display: block;">
                商品介绍模块内容
            </div>
            <div class="item">
                规格与包装模块内容
            </div>
            <div class="item">
                售后保障模块内容
            </div>
            <div class="item">
                商品评价(50000)模块内容
            </div>
            <div class="item">
                手机社区模块内容
            </div>

        </div>
    </div>
    <script>
        // 获取元素
        var tab_list = document.querySelector('.tab_list');
        var lis = tab_list.querySelectorAll('li');
        var items = document.querySelectorAll('.item');
        // for循环绑定点击事件
        for (var i = 0; i < lis.length; i++) {
            // 开始给5个小li 设置索引号 
            lis[i].setAttribute('index', i);
            lis[i].onclick = function() {
                // 1. 上的模块选项卡,点击某一个,当前这一个底色会是红色,其余不变(排他思想) 修改类名的方式
                // 干掉所有人 其余的li清除 class 这个类
                for (var i = 0; i < lis.length; i++) {
                    lis[i].className = '';
                }
                // 留下我自己 
                this.className = 'current';
                // 2. 下面的显示内容模块
                var index = this.getAttribute('index');
                console.log(index);
                // 干掉所有人 让其余的item 这些div 隐藏
                for (var i = 0; i < items.length; i++) {
                    items[i].style.display = 'none';
                }
                // 留下我自己 让对应的item 显示出来
                items[index].style.display = 'block';
            }
        }
    </script>
</body>
4.8 H5自定义属性

自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
自定义属性获取是通过getAttribute( ‘属性’ ) 获取。

1. 设置H5自定义属性

H5规定自定义属性用data- 开头作为属性名并且赋值。
例如 <div data-index = "1"></div>

2. 获取H5自定义属性

  • 兼容性获取 element.getAttribute('data-index');
  • H5新增 element.dataset.index 或者 element.dataset[ 'index' ] ie 11才开始支持

5. 节点操作

5.1 为什么学节点操作

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

1. 利用 DOM 提供的方法获取元素

  • document.getElementById();
  • document.getElementsByTagName();
  • document.querySelector();
  • 特点:逻辑性不强、繁琐

2. 利用节点层次关系获取元素

  • 利用父子兄节点关系获取元素
  • 特点:逻辑性强,兼容性差
5.2 节点概述

在这里插入图片描述
一般地,节点至少拥有 nodeType(节点类型)、nodeName(节点名称)、nodeValue(节点值)这三个基本属性。

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

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

1. 父级节点

node.parentNode

  • parentNode 属性可以返回某节点的父节点,注意是最近的一个父节点
  • 如果指定的节点没有父节点则返回 null
2. 子节点
  1. parentNode.childNodes (标准)

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

注意:返回值里面包含了所有的子节点,包括元素节点,文本节点等。
如果只想要获得里面的元素节点,则需要专门处理。所以我们一般不提倡用childNodes
在这里插入图片描述

  1. parentNode.children (非标准)

parentNode.children 是一个只读元素,返回所有子元素节点。它只返回元素节点,其余节点不返回(需要重点掌握

  1. parentNode.firstChild

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

  1. parentNode.lastChild

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

  1. parentNode.firstElementChild

firstElementChild 返回第一个子元素节点,找不到则返回null。

  1. parentNode.lastElementChild

lastElementChild 返回第一个子元素节点,找不到则返回null。
注意:这两个方法有兼容性问题,IE9以上才支持

实际开发中,获取第一个最后一个子节点使用方法为:
parentNode.children[0]
parentNode.children[parentNode.children.length - 1]

3. 兄弟节点
  1. node.nextSibling

nextSibling 返回当前元素的下一个兄弟节点,找不到则返回null。同样,也是包含所有节点。

  1. node.previousSibling

previousSibling 返回当前元素的上一个兄弟节点,找不到则返回null。同样,也是包含所有节点。

  1. node.nextElementSibling

nextElementSibling 返回当前元素的下一个兄弟元素节点,找不到则返回null。

  1. node.previousElementSibling

previousElementSibling 返回当前元素上一个兄弟元素节点,找不到则返回null。
注意:这两个方法有兼容性问题,IE9以上才支持

如若想解决兼容性,则可封装一个函数:
在这里插入图片描述

5.4 创建节点

document.creatElement( ‘tagName’ );

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

5.5 添加节点
  1. node.appendChild(child)

node.appendChild() 方法将一个节点添加到指定父节点的子节点列表末尾。类似于css里面的after 伪元素。

  1. node.insertBefore(child, 指定元素)

node.insertBefore() 方法将一个节点添加到父节点的指定子节点前面,类似于css 里面的before 伪元素。

简单版发布留言案例
<body>
    <textarea name="" id=""></textarea>
    <button>发布</button>
    <ul>

    </ul>
    <script>
        var btn = document.querySelector('button');
        var text = document.querySelector('textarea');
        var ul = document.querySelector('ul');
        btn.onclick = function(){
             if(text.value == ''){
                alert('您没有输入内容');
                return false;
            }else{
                // 1.创建元素
                var li = document.createElement('li');
                // 先有 li 才能赋值
                li.innerHTML = text.value;
                // 2.添加元素
                // ul.appendChild(li);
                ul.insertBefore(li,ul.childdren[0]);
            }
        }            
    </script>
</body>
5.6 删除节点

node.removeChild(child)

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

5.7 复制节点(克隆节点)

node.cloneNode()

node.cloneNode() 方法返回调用该方法的节点的一个副本。也称为克隆节点/拷贝节点。

注意:

  1. 如果括号参数为空或者为false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
  2. 如果括号参数为true,则是深度拷贝,会复制节点本身以及里面的所有子节点。
动态生成表格案例(重要)
<body>
    <table cellspacing="0">
        <thead>
            <tr>
                <th>姓名</th>
                <th>科目</th>
                <th>成绩</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
        
        </tbody>
    </table>
    <script>
        // 1.先准备学生数据
        var datas = [{
            name: '卫英络',
            subject: 'JS',
            score: 100
        },{
            name: '红利',
            subject: 'JS',
            score: 25
        },{
            name: '阿玛',
            subject: 'JS',
            score: 68
        },{
            name: '李武',
            subject: 'JS',
            score: 87
        }];
        // 2.往tbody 里面建行: 有几个人(通过数组的长度)我们就创建几行
        var tbody = document.querySelector('tbody');
        for(var i = 0; i < datas.length; i++){ //外层循环管 tr 行
            // 1. 创建 tr 行
            var tr = document.createElement('tr');
            tbody.appendChild(tr);
            // 2. 行里创建单元格(跟数据有关系的3个单元格) td 单元格数量取决于每个对象里面的属性个数 for循环遍历
            for(var k in datas[i]){ // 里层循环管 td 列
                // 创建单元格
                var td = document.createElement('td');
                // 把对象里面的属性值 datas[i][k] 给 td
                tr.appendChild(td);
                td.innerHTML = datas[i][k];
            }
            // 3. 创建有删除2个字的单元格
            var td = document.createElement('td');
            td.innerHTML = '<a href="javascript:;"> 删除 </a>'
            tr.appendChild(td);
        }
        // 4.删除操作 开始
        var as = document.querySelectorAll('a');
        for(var i = 0; i < as.length; i++){
            as[i].onclick = function(){
                // 点击a 删除 当前 a 所在的行(链接的爸爸的爸爸) node.removeChild(child)
                tbody.removeChild(this.parentNode.parentNode);

            }
        }
    </script>
</body>
5.7 三种动态创建元素区别
  • document.write()
  • element.innerHTML
  • document.createElement()

区别

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

总结:不同浏览器下,innerHTML 采取数组情况下效率要比 creatElement 高

6. DOM 重点核心(总结)

在这里插入图片描述
关于dom操作,我们主要针对于元素的操作。主要有创建、增、删、改、查、属性操作、事件操作。

6.1 创建

1. document.write
2. innerHTML
3. createElement

6.2 增

1. appendChild
2. insertBefore

6.3 删

1. removeChild

6.4 改

主要修改dom的元素属性,dom元素的内容、属性,比哦但的值等

  1. 修改元素属性:src、href、title
  2. 修改普通元素内容:innerHTML、innerText
  3. 修改表单元素:value、type、disabled
  4. 修改元素样式:style、className
6.5 查

主要获取查询dom的元素

  1. DOM提供的API方法:getElementById、getElementsByTagName 古老用法不太推荐
  2. H5提供的新方法:querySelector、querySelectorAll 提倡
  3. 利用节点操作获取元素:父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling) 提倡
6.6 属性操作

主要针对自定义属性。
1. setAttribute:设置dom的属性值
2. getAttribute:得到dom的属性值
3. removeAttribute:移除属性

6.7 事件操作

给元素注册事件,采取 事件源.事件类型 = 事件触发程序
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值