JavaScrip DOM

JavaScript核心 DOM 操作

Web API是浏览器提供的一套操作浏览器功能页面元素的API(BOM和DOM)。

DOM

文档对象模型(DOM) 是处理可扩展标记语言(HTML或者XML)的标准编程接口

在这里插入图片描述

DOM重点核心

DOM主要用来操作页面元素

我们获取过来的DOM元素都是一个对象(object)!!

所以称为文档对象模型获取元素


关于DOM。我们主要针对元素操作,主要有创建、增、删、改、查、属性操作、事件操作。

创建
    1. docum.write
    1. innerHTMLl
    1. creatElement
  • appendChild
  • insertBefore

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

  • 修改元素属性:src 、href、title等
  • 修改普通元素:innerHTML、innerText
  • 修改表单内容:value、disabled等
  • 修改元素样式:style、calssName
查(获取页面元素)
  • DOM提供的API方法: getElementByld()、getElementsByTagName() 古老用法不太推荐
  • H5提供的新方法:document.querySelector、document.querySelectorAll 提倡
  • 利用节点获取元素:父节点(parentNode)、子节点(children)、兄弟节点(nextElementSibling)、(previousElementSibling) 提倡
属性操作

主要针对自定义属性

  • setAttribute:设置dom的属性值
  • getAttribute:得到dom的属性值
  • removeAttribute:移除属性
事件操作

给元素注册事件

如何获取页面元素:

  • 根据ID获取

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

<body>
    <div id="time"> 2020-6-25</div>

    <script>
        // 1. 文档页面从上面往下加载,要先有便签 所以script写到标签下面
        // 2. get 获得 element 元素 by 通过 
        // 3. 参数 id是大小写敏感的字符串
        // 4. 返回的是一个元素对象
    var timer = document.getElementById('time')
    console.log(timer);   
    console.log(typeof timer);   
    //  console.dir(timer) 打印我们返回的元素对象 更好的查看里面的属性和方法
    console.dir(timer)
    </script>
</body>
  • 根据标签名获取

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


​ 使用element.getElementsByTagName(‘标签名’);

​ 可以获取某个元素(父元素)内部所有指定标签名的子元素

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

<body>
    <div>
        <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>
    </div>

    <script>
        //1. 返回的是  元素对象的集合 以伪数组的形势存储的
        var lis = document.getElementsByTagName('li');
        console.log(lis);        
        console.log(lis[0]);
        // 一次打印里面的元素对象  可以用遍历
        for(var i = 0;i < lis.length ;i++){
            console.log(lis[i]);           
        }
        // 3.如果页面中只有一个li 返回的还是伪数组的形式
        // 4.如果页面中没有这个元素 返回的是一个空的伪数组
        // 5.element.getElementsByTagName('标签名');
        console.log('--------------------------------------------');
        var ol = document.getElementById('ol')
        console.log(ol.getElementsByTagName('li'));
        
    </script>
</body>
  • 通过HTML5新增方法获取 (ie9以上版本支持)
  1.document.getElementsByCalssName('类名');//根据类名返回元素对象集合
  2.document.querySelector('选择器');		 //根据指定选择器返回第一个元素对象
  3.document.querySelectorAll('选择器');	//根据指定选择器返回所有元素
//--------------------------------------------------------------------------
<body>
    <div class="box">盒子1</div>
    <div class="box">盒子2</div>
    <div id="nav">
        <ul>
            <li>首页</li>
            <li>导航</li>
        </ul>
    </div>

    <script>
        //  1.document.getElementsByCalssName('类名');//根据类名返回元素对象集合
        var boxs = document.getElementsByClassName('box');
        console.log(boxs);
        console.log('----------------------------------------------');        
        //   2.document.querySelector('选择器');//返回指定选择器的第一个元素对象
        // 切记 里面的选择器需要加符号 .box  #nav
        var box = document.querySelector('.box');
        console.log(box);
        var nav = document.querySelector('#nav');
        console.log(nav);
        var li = document.querySelector('li');
        console.log(li);
        console.log('--------------------------------------------------');
        // 3.document.querySelectorAll('选择器');返回指定选择器所有元素对象
        var allBox = document.querySelectorAll('.box')
        console.log(allBox);
        var lis = document.querySelectorAll('li')
        console.log(lis);      
    </script>
</body>
  • 特殊元素获取(body,html)

获取body元素

<script>
        var bodyEle = document.body;
        console.log(bodyEle);
        console.dir(bodyEle);
		//返回body元素对象
</script>

获取html元素

<script>
      var htmlEle = document.documentElement;
      console.log(htmlEle);
		//返回html元素对象
</script>

事件基础

​ js使我们有能力创建动态页面,而事件是可以被js侦测到的行为。

​ 简单理解:触发----响应机制。

​ 网页中每一个元素都可以产生某些可以触发js的事件,例如,我们可以在用户点击某个按钮时产生一个事件,然后去执行某些操作。

事件三要素
 <button id="btn">按钮</button>
    <script>
        // 点击按钮弹出对话框
        // 事件是有三部分组成  事件源 时间类型  事件处理程序  称为事件三要素
        // (1)事件源  事件被触发对象 谁 按钮
        var btn = document.getElementById('btn');
        // (2) 事件类型 如何触发 什么事件 比如鼠标点击事件(onclick) 
        //(3) 事件处理程序  通过函数赋值的方式 完成
        btn.onclick = function(){
            alert('您点击了按钮');
        }
    </script>
执行事件过程

​ 执行事件的步骤

  1. 获取事件源
  2. 注册事件(绑定事件)
  3. 添加事件处理程序(采取函数赋值的形式)
 <div id="div1">123</div>
    <script>
        // var div = document.querySelector('div')
        // div.onclick = function (){
        //     alert('456')
        // }
        // 执行事件步骤
        // 点击div 弹出窗口 456
        // 1.获取事件源
        var div1 = document.getElementById('div1')
        // 2.绑定事件
        // div1.onclick
        // 3.添加事件处理程序        
        div1.onclick = function(){
            alert('456');
        }

    </script>
常见鼠标事件

在这里插入图片描述

操作元素

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

改变元素内容
1.element.innerText
//从起始位置到终止位置的内容,但它去除html便签,同时空格和换行也会去掉
//不会识别html标签  非标准
2.element.innerHTML
//从起始位置到终止位置的内容,包括html便签,同时保留空格和换行
//识别html标签  w3c标准


//-------------------------------------------------------------
//这两个属性是可读写的  可以获取元素里面的内容 
<p>我是文字
       <span>123</span>
</p>
    
    <script>
        var p = document.querySelector('p')
        console.log(p.innerText);     
    </script>



<head>  
    <style>
        div ,p {
            width: 200px;
            height: 30px;
            background-color: coral;
            text-align: center;
        }
    </style>
</head>
<body>
    <button>点击查看时间</button>
    <div>时间</div>
    <p></p>
    <script>
        var bnt = document.querySelector('button');
        var div = document.querySelector('div');
        bnt.onclick = function(){
            div.innerText = getDate();
        }
        function getDate(){
                    // 格式化年月日
            var date = new Date();      
            var year = date.getFullYear();
            var month = date.getMonth() + 1;
            var date = date.getDate();
            return year+'年'+month+'月'+date+'日';			  
        }
        var p = document.querySelector('p')
        // 我们元素也可以不用添加事件
        p.innerText = getDate()
    </script>
</body>

改变元素属性
  1. innerText, innerHTML 改变元素内容

  2. src ,href

  3. id ,alt,title

修改元素属性src 其余都是类似的

<body>
    <button id="ldh">图一</button>
    <button id="zxy">图二</button>
    <img src="timg.jpg" >
	<!-- <img src="timg%20(1).jpg" > -->
 <script>
    var ldh = document.getElementById('ldh');
	var zxy = document.getElementById('zxy');
	var img = document.querySelector('img')
	zxy.onclick = function(){
		img.src = 'timg%20(1).jpg';
	}
	ldh.onclick = function(){
		img.src = 'timg.jpg';
	}
 </script>
</body>

案例 分时问候

视频讲解

修改表单属性

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

type(类型属性)、value(值属性)、checked(选择)、selected、disabled(表单是否被使用)

<body>
    <button >按钮</button>
	<input type="" name="" id="" value="输入内容" />
   
	
 <script>
    var button = document.querySelector('button');
	var input = document.querySelector('input');
	button.onclick = function(){
		// input.innerHTML  用来修改div里面的内容  不能用来修改表单
		// 表单里面的值通过属性来修改  如文字内容用value修改
		input.value = '被点击了';
		// 如果想要某个表单被禁用 不能点击用 disabled 下面两个都可以
		// button.disabled = true ;
		// this 指向的是事件函数的调用者 button
		this.disabled = true ;
	}
 </script>
</body>
密码明文显示案例(x)

视频讲解

修改样式属性

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

  1. element.style 行内样式操作

样式比较少 或者功能比较简单的时候使用

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>
		div{
			width: 300px;
			height: 300px;
			background-color: chartreuse;
		}
	</style>
</head>
<body>
	<div></div>
	<script>
		var div = document.querySelector('div');
		div.onclick = function(){
			// div.style里面的属性用驼峰命名法
			div.style.backgroundColor = 'pink';
			div.style.width = '600px';
		}
	</script>
</body>
</html>
  1. element.className 类名样式操作

适合样式较多或者功能复杂的情况

修改后会覆盖(修改)原来的类名

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>
		div{
			width: 300px;
			height: 300px;
			background-color: chartreuse;
		}
		.change{
			width: 600px;
			height: 300px;
			background-color: coral;
			margin-top: 50px;
			font-size: 50px;
			color: cornsilk;
		}
	</style>
</head>
<body>
	<div class="first">123</div> 
	<script>
		var div = document.querySelector('div');
		div.onclick = function(){
			// 让我们当前元素的类名改为了change

			// div.className = 'change'

			// 如果要保留原来的类名 可以这样做  多类名选择器
			div.className = 'first change';
		}
	</script>
</body>
</html>
关闭二维码案例

https://www.bilibili.com/video/BV1k4411w7sV?p=20

for循环设置多组小图标案例

https://www.bilibili.com/video/BV1k4411w7sV?p=21

显示隐藏文本框类容案例

https://www.bilibili.com/video/BV1k4411w7sV?p=22

密码框验证信息提示案例 (密码较短…)

https://www.bilibili.com/video/BV1k4411w7sV?p=24

在这里插入图片描述

在这里插入图片描述

关闭广告案例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title></title>
    <style>
        div{
            height: 200px;
            width: 200px;
            background-color: cornflowerblue;
            text-align: center;
            line-height: 180px;
            margin: 100px auto ;
            font-size: 30px;
            color: cornsilk;
        }
        p {
            width: 30px;
            height: 30px;
            background-color: darkorange;
            color: darkslategray;
            text-align: center;
            line-height: 20px;
            position: relative;
            top: -280px;
            left: 810px;      
            /* display: none;      */
            cursor: pointer;

}
        
    </style>
</head>
<body>
    <div>这是小广告</div>
    <p>x</p>
    <script>
        // 获取实践源
        var p = document.querySelector('p')
        var div = document.querySelector('div')
        // 添加注册事件
        p.onclick = function(){
            div.style.display = 'none';
        }

    </script>
</body>
</html>

开关灯

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body{
            background-color: white;
        }
    </style>
</head>
<body>
    <button id="douse">关灯</button>
    <button id="openBnt">开灯</button>
    <script>
        // 获取事件源
        var douse = document.getElementById('douse')
        var openBnt = document.getElementById('openBnt')
        var body = document.querySelector('body');
        // 注册事件
        douse.onclick = function(){
             body.style.backgroundColor = 'black';
        }
        openBnt.onclick = function (){
            body.style.backgroundColor = 'white';
        }
    </script>
</body>
</html>
排他思想(算法)

1.给所有元素清除样式

2.给当前元素设置样式

顺序不能颠倒

<!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>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>

    <script>
        var btn = document.getElementsByTagName('button');
        // bnt得到的是伪数组  里面的每个元素是btn[i]
        // 遍历数组把所有的btn绑定函数  循环注册事件

        for (var i = 0; i < btn.length; i++) {
            // 记录索引号
            this.btn[i].index = i;
            btn[i].onclick = function () {
                console.log(this.index);
                console.log(this);
                console.log(btn);
                // 把所有的按钮先清空样式               
                for (var i = 0; i < btn.length; i++) {
                    btn[i].style.backgroundColor = '';
                }
                // 为当前元素修改样式
                this.style.backgroundColor = 'pink';
            }

        }
    </script>
</body>

</html>
百度换肤案例

https://www.bilibili.com/video/BV1k4411w7sV?p=27

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body{
            background-color: pink;
        }
        div {
            border: slateblue 1px solid;
            margin: 5px;
            float: left;
        }
        div:first-child{
            width: 100px;
            height: 100px;
            background-color: pink;
           
        }
        div:nth-child(2){
            width: 100px;
            height: 100px;
            background-color: plum;
        }
        div:nth-child(3){
            width: 100px;
            height: 100px;
            background-color:palegreen;
        }
        div:nth-child(4){
            width: 100px;
            height: 100px;
            background-color: salmon;
        }
    </style>
</head>
<body>
    <div id="pink"></div>
    <div  id="plum"></div>
    <div  id="palegreen"></div>
    <div  id="salmon"></div>
   
    
    <script>
        // 获取事件源
        var body = document.querySelector('body');
        var pink = document.getElementById('pink');
        var plum = document.getElementById('plum');
        var palegreen = document.getElementById('palegreen');
        var salmon = document.getElementById('salmon');

        pink.onclick = function(){
            body.style.backgroundColor = 'pink';
        }
        plum.onclick = function(){
            body.style.backgroundColor = 'plum';
        }
        palegreen.onclick = function (){
            body.style.backgroundColor = 'palegreen';
        }
        salmon.onclick = function(){
            body.style.backgroundColor = 'salmon';
        }
      
    </script>
</body>
</html>
表格隔行换色案例(x)

https://www.bilibili.com/video/BV1k4411w7sV?p=28

表单全选案例

https://www.bilibili.com/video/BV1k4411w7sV?t=4&p=29

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
        <style>
            table{
                margin: 100px auto;
                width: 40vh;
                height: 30vh;
                /* border: chartreuse 1px solid; */
            }
            thead>tr>th{
                width: 100vh;
                height: 40px;
               background-color:#008CD0;
            }
            tbody{
                background-color: RGB(244,240,245);
                text-align: center;
            }
        </style>
</head>
<body>
    <div class="warp">
        <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>手机1</td>
                    <td>500</td>
                </tr>
                <tr>
                    <td><input type="checkbox"></td>
                    <td>手机1</td>
                    <td>500</td>
                </tr>
                <tr>
                    <td><input type="checkbox"></td>
                    <td>手机1</td>
                    <td>500</td>
                </tr>
            </tbody>   
        </table>        
    </div>

    <div></div>
    <script>
        // 1.全选和取消全选的做法:让下面所有复选框的checked属性(选中状态)跟随 全选按钮即可
        // 获取元素
        var j_cbAll = document.getElementById('j_cbAll'); //全选按钮
        var j_tbs = document.getElementById('j_tb').getElementsByTagName('input')//下面所有的复选框
        // 注册事件
        j_cbAll.onclick = function(){
            console.log(j_cbAll.checked);
            for(var i = 0 ; i < j_tbs.length ;i++){
                j_tbs[i].checked = j_cbAll.checked;
            }
        }

        // 2.下面复选框需要全部选中,上面复选框才能选中做法:给下面所有复选框绑定事件,每次点击,都要循环查看下面所有的复选框是否有没选中的,如果有一个没选中的,上面全选就不选中
        //   可以设置一个变量,来控制是否全部选中。
        for(var i = 1 ; i < j_tbs.length ; i++){
            j_tbs[i].onclick = function (){
                // flag 控制 全选按钮是否被选中   
                var flag = true;

                // 每次点击下面的复选框都要循环4个小按钮是否全部被选中
                for(var i = 1 ; i < j_tbs.length ; i++){
                    if(!j_tbs[i].checked){
                        flag = false;
                        break;//只要有一个没有选中 就直接退出for循环,这样可以提高效率
                    }
                }
                j_cbAll.checked = flag;
            }
        }

    </script>
</body>
</html>
自定义属性操作

获取属性值

  • element.属性
  • element.getAttribute(‘属性’)

区别:

  • element.属性 获取内置属性值
  • element.getAttribute(‘属性’); 主要获得自定义属性(标准)

修改属性

(1) element.属性 = ‘值’

(2) element.setAttribute(‘属性’,‘值’) ; 主要针对自定义属性

移除属性

(1)element.removAttribute(属性)

代码总结

<body>
    <div id="deom" index='1' class="n"></div>
    <script>
        var div = document.querySelector('div');       
        // 1.获取元素的属性
        // (1) element.属性
        console.log(div.id);
        // (2) element.getAttribute('属性') get 得到  attribute 属性的意思
        // 我们程序员自己添加的属性称为自定义属性
        // 上面div里面的  index='1'  index就是自定义属性
        console.log(div.getAttribute('id'));
        console.log(div.getAttribute('index'));
        // ------------------------------------------------------
        // 2.设置属性值
        // (1) element.属性 = '值'
        div.id = 'test'
        console.log(div.id);       
        div.className = '123'
        // (2) element.setAttribute('属性','值') ; 主要针对自定义属性
        div.setAttribute('index',3);
        div.setAttribute('calss','foot')//class比较特殊 这里写的是class不是calssName
  		// ------------------------------------------------------
        // 3.移除属性 removAttribute(属性)
        div.removeAttribute('index');

    </script>
</body>
tab栏切换布局案例(重要)
  1. Tab切换分为上下两个模块
  2. 上面的模块选项卡,点击某一个,被选中的选项底色会变成红色,其余不变(排他思想) 修改类名的方式
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        li {
            list-style: none;
        }
        .tab {
            width: 1000px;
            margin: 100px auto;
            height: 300px;
            /* background-color: teal; */
        }

        .tab_list {
            width: 1040px;
            /* background-color: #F5F0F5;  */
        }

        .tab_list>ul {
            width: 1000px;
            height: 40px;
            line-height: 40px;
            /* background-color: red; */
            /* border: #ccc 1px solid; */
            border-bottom: 2px #D4281F solid;
        }

        .tab_list>ul>li {
            float: left;
            padding: 0 30px;
            cursor: pointer;
        }

        .current {
            background-color: #D4281F;
            color: #F5F0F5;
            /* margin-left: -40px; */
        }

        .tab_con {
            margin-left: 45px;
        }

        .item {
            display: none;
        }
    </style>
</head>
<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>
        // 1. 上面的模块选项卡,点击某一个,被选中的选项底色会变成红色,其余不变(排他思想)  修改类名的方式
        // 获取元素
        var tab_list = document.querySelector('.tab_list');
        var lis = tab_list.querySelectorAll('li');
        var items = document.getElementsByClassName('item');

        //for 循环绑定所有模块选项卡的li
        for (var i = 0; i < lis.length; i++) {
            // 开始给五个li设置索引号
            lis[i].setAttribute('index', i);
            lis[i].onclick = function () {
                //排他思想 清空li所有样式
                for (var i = 0; i < lis.length; i++) {
                    lis[i].className = '';
                }
                //留下当前点击的li的样式  this
                this.className = 'current';
                //    2. 下面的显示内容模块
                //    核心思路 给上面的tab_list 里面所有的li添加自定义属性,属性值从0号开始编号                                    
                var index = this.getAttribute('index');
                console.log(index);   
                // 排他思想 让其余item 这些div隐藏 
                // 留下点击的当前div
                for (var i = 0; i < items.length; i++) {
                    items[i].style.display = 'none'
                }
                items[index].style.display = 'block'
            }
        }
   </script>
</body>
</html>
H5自定义属性

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

1.设置H5自定义属性

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

比如


<div data-index = '1' > </div>

//或者使用js设置
element.setAtteribute('data-index',3)

2.获得H5自定义属性

//1.兼容性获取
element.getAtteribute('data-index');

//2. H5新增的获取自定义属性  elemen.dataset.index 或者  element.dataset['index']  只能获取data-		开头的   ie11才兼容

//dataset 是一个集合里面存放了所有以data开头的自定义属性
console.log(div.dataset);
console.log(div.dataset.index);

//如果自定义属性里面有多个-连接的单词 ,我们获取的时候采取驼峰命名法。
<div data-last-name = 'andy'> </div>
console.log(div.dataset.lastName);
console.log(dav.sataset['lastName']);

节点操作

利用节点层级关系获取元素

​ 利用父子兄弟节点关系获取元素

​ 逻辑性枪法,但兼容性差

节点概述

​ 一般节点至少拥有 nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)

​ 三个基本属性

nodeType(节点类型)

​ 元素节点的nodeType 为 1

​ 属性节点 为 2

​ 文本节点 为 3 (文本节点包括文字、空格、换行等)

实际开发,节点操作主要操作元素节点

获取父节点和子节点
<!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>
    <!-- 利用节点层级关系获取元素
        利用父子兄弟节点关系获取元素
        逻辑性强,但兼容性差
   --------------------------------------------------------------        
        节点概述
        一般节点至少拥有 nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)
        三个基本属性
----------------------------------------------------------------
        nodeType(节点类型)
        元素节点的nodeType 为 1
        属性节点 为 2
        文本节点 为 3 (文本节点包括文字、空格、换行等)
        实际开发,节点操作主要操作元素节点
        -----------------------------------------------
        节点层级
        利用DOM输可以把节点划分成不同的层级关系
        1.父级节点
    -->


    <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="erweima">x</span>
    </div>
    <script>
        //1. 父节点 parentNode
        var  erweima = document.querySelector('.erweima');
        // console.log(erweima);
        // 得到的是距离元素最近的父节点  找不到父节点返回为空
        console.log(erweima.parentNode);
        console.log('------------------------------------------------------------------');
        
        // 2.子节点  
        // (1)childNodes 得到所有的子节点 包含元素节点 和文本节点 等等
        var ul = document.querySelector('ul');
        console.log(ul.childNodes);
        // 如果只想要获得里面的元素节点,则需要专门处理。 所以一般不提倡使用childNodes
        // 处理方法

        for(var i = 0;i < ul.childNodes.length ; i++){
            if(ul.childNodes[i].nodeType == 1){
                console.log(ul.childNodes[i]);           
            }
        }
        // console.log('-------------------------------------------------');
        
        // (2)children (非标准) 只能获得子元素节点 其余节点不返回(需要重点掌握)
        // 基本兼容 放心使用
        console.log(ul.children);
        
    </script>
</body>
</html>
首尾子节点获取
<!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>
    <!-- 
       

        实际开发中 .firstChild 和  .lastChild 操作不方便
        .firstElementChild 和 .lastElementChild 有兼容性问题 ie9以上才支持


     -->
    <ol>
        <li>我是li1</li>
        <li>我是li2</li>
        <li>我是li3</li>
        <li>我是li4</li>
    </ol>

    <script>

        var ol = document.querySelector('ol');
        // .firstChild  第一个子节点 不管是文本节点还是元素节点
        console.log(ol.firstChild);       
        // .lastChild 最后一个 不管是文本节点还是元素节点
        console.log(ol.lastChild);
        // .firstElementChild  第一个子元素节点
         console.log(ol.firstElementChild);
        // .lastElementChild 最后一个子元素节点
        console.log(ol.lastElementChild);
        
        console.log('------------------------------------------------------');

        // 实际开发写法
        console.log(ol.children[0]);
        console.log(ol.children[1]);
        console.log(ol.children[2]);
        // 最后一可能不确定  用 Element.children.length - 1
        console.log(ol.children[ol.children.length - 1]);                
    </script>
</body>
</html>
下拉菜单案例

https://www.bilibili.com/video/BV1k4411w7sV?p=41

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

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>
		body,
		li,
		a {
			margin: 0;
			padding: 0;
			list-style: none;
			text-decoration: none
		}

		.nav {
			width: 500px;
			height: 280px;
			margin: 100px auto;
			/* border: olivedrab 1px solid; */
			display: flex;
		}

		.nav>li {
			position: relative;
			/* display: flex; */


		}

		.nav>li>a {
			display: block;
			height: 40px;
			width: 72px;
			background-color: rgba(255, 255, 255, 0.904);
			margin-bottom: 1px;
			text-align: center;
			line-height: 40px;
			color: rgb(66, 66, 66);
			border-bottom: tomato 1px solid;
		}

		.nav>li>a:hover {
			color: white;
			background-color: tomato;
		}

		.nav>li>ul {
			position: absolute;
			top: 42px;
			left: -40px;
			width: 60px;
			height: 180px;
			cursor: pointer;
			/* border: steelblue 1px solid; */
			display: none;

			
		}

		.nav>li>ul>li {
			/* position: absolute; */
			border-left: rgb(247, 165, 150) 1px solid;
			border-right: rgb(247, 165, 150) 1px solid;
			border-bottom: rgb(247, 165, 150) 1px solid;
			/* display: none; */
			width: 100%;
			height: 30px;
			text-align: center;
			padding: 5px;
			margin-bottom: 1px;
		}

		.nav>li>ul>li:hover {
			background-color: rgb(247, 165, 150);
			color: rgb(253, 253, 212);
		}
	</style>
</head>

<body>
	<ul class="nav">		
		<li>
			<a href="#">微博</a>
			<ul>
				<li>私信</li>
				<li>读评论</li>
				<li>@我</li>
			</ul>
		</li>
		<li>
			<a href="#">微博</a>
			<ul>
				<li>私信</li>
				<li>读评论</li>
				<li>@我</li>
			</ul>
		</li>
		<li>
			<a href="#">微博</a>
			<ul>
				<li>私信</li>
				<li>读评论</li>
				<li>@我</li>
			</ul>
		</li>
		<li>
			<a href="#">微博</a>
			<ul>
				<li>私信</li>
				<li>读评论</li>
				<li>@我</li>
			</ul>
		</li>			
	</ul>

	<script>
		// 获取元素
		var nav = document.querySelector('.nav')
		var lis = nav.children;//得到四个li
		console.log(nav);		
		console.log(nav.children);		
		console.log(lis);
		
		// 循环 所有li 注册事件
		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>
</body>

</html>
兄弟节点
<!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>this div</div>
    <span>this span</span>
    <script>
        var div = document.querySelector('div');
        // .nextSibling 得到下一个兄弟节点 包含所有节点 找不到返回空
        var span = div.nextSibling;
        console.log(span);
        // .previouSibling 得到上一个兄弟节点,包含所有节点  找不到返回空
        console.log(div.previousSibling);
        console.log('--------------------------------');
        
        //部分不兼容  得到下一个兄弟的元素节点
        console.log(div.nextElementSibling);
        // 部分不兼容 得到上一个兄弟的元素节点
        console.log(div.previousElementSibling);
        
		// 目前解决方法 自己封装一个函数
        
    </script>
</body>
</html>
创建和添加节点

document.write()方法 了解就好

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

<!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>
    <!-- 
         创建节点  document.createElement('tagName')
         document.createElement() 方法创建由 tagName 指定的HTML元素。
         因为这些元素原先不存在是根据我们的需求动态生成的,所以我们也称为  动态创建节点 
    -->
    <!--
        添加节点 
        1. node.appendChlid(chlid)
        node.appendChlid(chlid) 方法将一个节点添加到指定父元素的子节点列表末尾 类似添加数组元素的push。
        例如 css 里面的after 伪元素
        2. ul.appendChild(child,指定元素);
    
    -->

    <ul>
        <li>123</li>
    </ul>

    <script>
        //获取元素
        var ul = document.querySelector('ul');
        // 1. 创建元素节点
        var li = document.createElement('li');
        // 2.添加节点 node.appendChlid(chlid) node 父级 child 子级   类似添加数组元素的push。
        ul.appendChild(li);
        // 3. 添加节点 ul.appendChild(child,指定元素);
        var lili = document.createElement('li');
        ul.insertBefore(lili, ul.children[0]);
        // 4. 我们想要页面 添加新的元素 先创建元素 再添加元素

//---------------------高级做法 ----------------------------------------------------------------
		insertAdjacentHTML可以直接插入html节点
        // 创建li和section
        var li = ' <li class=""><span>新选项卡</span><i class="">x</i></li>'

        // 把创建好的元素追加到对应父元素里面
        // 原來做法:动态创建元素 但是元素里面的内容比较多,需要innerHTML赋值,再appendChild追加到父元素里面
        // 高级做法:利用insertAdjacentHTML()可以直接把字符串格式元素添加到父元素中
        //appendChild不支持追截字符串的子元素,insertAdjacentHTML支持追加字符串的子元素 
        that.ul.insertAdjacentHTML('beforeEnd', li)
    </script>
</body>

</html>
insertAdjacentHTML文档

https://developer.mozilla.org/zh-CN/docs/Web/API/Element/insertAdjacentHTML

留言发布案例 ()

textarea 没有value值 暂时实现不了 (x)

textarea 改成input 完成了(√)

https://www.bilibili.com/video/BV1k4411w7sV?t=94&p=44

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    div {
      width: 600px;
      height: 400px;
      /* border: 1px red solid; */
      margin: 300px auto;
      position: relative;
    }

    li {
      background-color: sandybrown;
      margin-bottom: 10px;
      margin-left: -40px;
      /* list-style-type: none; */
      font-size: 30px;
      color: white;
    }

    input {
      position: absolute;
      top: -217px;
      left: 0px;
      /* border-radius: 20px; */
      display: block;
      margin: 0px auto;
      width: 300px;
      height: 200px;
      font-size: 20px;
    }

    button {
      position: absolute;
      top: -34px;
      left: 312px;
      /* border-radius: 20px; */
    }
  </style>
</head>

<body>
  <!-- 
        核心思路:点击按钮之后就创建一个li,添加到ul里面。
        在创建li的同事,把文本域里面的值通过li.innerHTML赋值给li
        如果想要新的留言后面显示就用appendChild 想要前面显示就用inserBefor
     -->
  <div>
    <input id="text" type="text " value="">
    <button>发布评论</button>
    <ul>
      <li>我是神评论</li>
    </ul>

  </div>

  <script>
    // 获取元素

    var btn = document.querySelector('button');
    var input = document.getElementById('text');
    var ul = document.querySelector('ul');
    console.log(input);
    // console.log(input.value);    
    // 注册事件
    btn.onclick = function () {
      // 创建元素
      var li = document.createElement('li');
      if (input.value == 0) {
        alert('请输入评论');
      }
      else {
        // 先有li 才能赋值                
        li.innerHTML = input.value;
        // 添加元素
        ul.appendChild(li);
      }

    }
  </script>
</body>

</html>
删除节点
<!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>
    <!--
        删除节点 node.removeChild(child)
        node.removeChild() 方法从 DOM 中 删除一个子节点 ,返回删除的节点
    -->

    <button>删除</button>
    <ul>
        <li>熊大</li>
        <li>熊二</li>
        <li>光头强</li>
    </ul>

      <script>
        //   获取元素
        var btn = document.querySelector('button');
        var ul = document.querySelector('ul');
        // 注册事件       
        btn.onclick = function (){
           if(ul.children.length == 0){
               this.disabled = true
           }
           else{
            ul.removeChild(ul.children[0]) 
           }
        }
      </script>
</body>
</html>
删除留言案例(a待完善)

https://www.bilibili.com/video/BV1k4411w7sV?t=92&p=46

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            width: 600px;
            height: 400px;
            /* border: 1px red solid; */
            margin: 300px auto;
            position: relative;
        }

        li {
            background-color: sandybrown;
            margin-bottom: 10px;
            margin-left: -40px;
            /* list-style-type: none; */
            font-size: 30px;
            color: white;
        }

        li a {
            /* display: inline-block; */
            border-radius: 10px;
            float: right;
            line-height: 40px;
            text-decoration: none;
            color: rgb(0, 136, 136);
            font-size: 16px;
            margin-left: 350px;
            /* background-color: khaki; */

        }

        input {
            position: absolute;
            top: -217px;
            left: 0px;
            /* border-radius: 20px; */
            display: block;
            margin: 0px auto;
            width: 300px;
            height: 200px;
            font-size: 20px;
        }

        button {
            position: absolute;
            top: -34px;
            left: 312px;
            /* border-radius: 20px; */
        }
    </style>
</head>

<body>
    <!-- 
        核心思路:点击按钮之后就创建一个li,添加到ul里面。
        在创建li的同事,把文本域里面的值通过li.innerHTML赋值给li
        如果想要新的留言后面显示就用appendChild 想要前面显示就用inserBefor
     -->
    <div>
        <input id="text" type="text " value="">
        <button>发布评论</button>
        <ul>
            <!-- <li>我是神评论<a href='#'>删除</a></li> -->
        </ul>

    </div>

    <script>
        // 获取元素

        var btn = document.querySelector('button');
        var input = document.getElementById('text');
        var ul = document.querySelector('ul');
        console.log(input);
        // console.log(input.value);    
        // 注册事件
        btn.onclick = function () {
            // 创建元素
            var li = document.createElement('li');
            if (input.value == '') {
                alert('请输入评论');
            }
            else {
                // 先有li 才能赋值                
                li.innerHTML = input.value + " <a href=''>删除</a>";
                // 添加元素
                ul.insertBefore(li, ul.children[0]);

                //   删除元素 删除的是当前链接的li  a的父级
                var as = document.querySelector('a');
                for (var i = 0; i < as.length; i++) {


                    as[i].onclick = function () {
                        // node.removeChild(chile); 删除的是li 是当前a链接所在的li this.parentNode;
                        ul.removeChild(this.parentNode);
                        console.log(a[i]);
                    }
                }
            }

        }
    </script>
</body>

</html>
复制节点(克隆节点)
<!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>
    <!-- 
        复制节点 (克隆节点)
        node.cloneNode()
        node.cloneNode() 方法返回调用该方法的节点的一个副本,也称为克隆节点

        注意: 如果方法的括号内参数为空或者false,则是浅拷贝,即只克隆节点本身,不克隆里面的子节点。
                如果括号里面为ture 深拷贝 复制里面的标签并复制里面的内容
     -->
    <ul id="ul">
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
    <script>
        var ul = document.getElementById('ul');
        console.log(ul);

        // 括号内参数为空 浅拷贝,只克隆节点本身
        var lili = ul.children[0].cloneNode(true);
        console.log(lili);
        ul.appendChild(lili)
    </script>
</body>

</html>
动态生成表格案例

创建学生信息

https://www.bilibili.com/video/BV1k4411w7sV?p=48

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        table{
            width: 500px;
            /* height: 200px; */
            /* background-color: darkgray; */
            margin: 100px auto;
        }

        thead{
            /* display: inline-block; */
        
            /* padding: 20px; */
            text-align: center;
            padding: 10px;
            background-color: darksalmon;
            color: ghostwhite;
            
        }
        td{
            border: lightcoral 1px solid;
            text-align: center;
            font-size: 14px;
        }
    </style>

</head>

<body>
    <table>
        <thead>
            <tr>
                <th>姓名</th>
                <th>年龄</th>
                <th>性别</th>
                <th>操作</th>
            </tr>
        </thead>

        <tbody>

        </tbody>

    </table>
</body>

<script>
    // 先去准备好学生数据 模拟数据库
    var datas = [
        {
            name : '阿呆',
            age : 20,
            sex : 'boy'
        },
        {
            name : '小红',
            age : 21,
            sex : 'girl'
        },
        {
            name : '小黑',
            age : 22,
            sex : 'boy'
        },
        {
            name : '张三',
            age : 35,
            sex : 'boy'
        },
    ];
    
        // 往tbody 里面创建行 , 有几个人我们就创建几行
        var tboty = document.querySelector('tbody');
        for(var i = 0; i < datas.length;i++){
            // 创建tr行
            var tr = document.createElement('tr');
            tboty.appendChild(tr);
            // 行里面创建单元格td(和数据有关) 单元格的数量取决于每个对象里面的属性个数 用for循环遍历对象

            for(var k in datas[i]){
                // 创建单元格td
                var td = document.createElement('td');
                // 把对象的属性值 datas[i][k] 给td
                td.innerHTML = datas[i][k];
                tr.appendChild(td)
            }
            // 创建 删除 单元格
            var td = document.createElement('td');
            td.innerHTML = '<a href="javascript:;">删除</a>';
            tr.appendChild(td);
        }
        // 删除操作 开始
        var as = document.querySelectorAll('a')
        for(var i = 0 ; i < as.length ; i++){
            as[i].onclick = function (){
                // 点击a 删除 当前a所在的行(a父级的父级)
                tboty.removeChild( this.parentNode.parentNode)
             
            }
        }
</script>
</html>

在这里插入图片描述

事件高级导读

注册事件

注册事件有两种方式:传统方式(前面学习的就是传统方式)和方法监听注册方式


传统方式:

  • on开头的事件 例如:onclick
  • 特点: 注册事件的唯一性
  • 同一个事件只能设置一个梳理数据,最后注册的处理函数将会覆盖注册的处理函数

方法监听注册方式:addEventListener()

  • w3c标准 推荐方式

  • addEventListener() 它是一个方法

  • 特点:同一个元素同一个事件可以注册多个监听器

  • 按照注册顺序依次执行

    ie9之前的版本支持attachEvent() (了解) 一般用不到

语法

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

eventTarget.addEventListener()方法将指定的监听器注册到eventTarget(目标对象)上,当改对象触发指定的事件时。就会执行事件处理函数。

三个参数

type:事件类型字符串,比如click mouseover,注意这里不要带on

listener:事件处理函数,事件发生时会调用改监听函数

useCapture:可选参数,是一个布尔值,默认false。之后学

<!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>
  <button>方法监听注册事件</button>
  <button id="attachEvent">attachEvent</button>
  <script>
    var btn = document.querySelector('button');
    // addEventListener里面的事件类型是字符串 必定加引号而且不带on
    // 同一个元素同一个事件可以注册多个监听器(事件处理程序)
    btn.addEventListener('click', function () {
      alert('123');
    })
    btn.addEventListener('click', function () {
      alert('456');
    })
    // -----------------------------------------------
    // attachEvent()
    // ie9之前的版本支持attachEvent() (了解)方法
    // 谷歌浏览器不支持了会报错
    // 封装函数解决报错
    btn2 = document.querySelector('#attachEvent')
    // console.log(btn2);
    btn2.attachEvent('onclick', function () {
      // alert('attachEvent')
    })

  </script>
</body>

</html>
删除事件(解绑事件)

https://www.bilibili.com/video/BV1k4411w7sV?t=31&p=60

删除事件兼容性解决方案七分半

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    div {
      width: 100px;
      height: 100px;
      background-color: cornflowerblue;
    }
  </style>
</head>

<body>
  <div>1</div>
  <div>2</div>
  <div>3</div>

  <script>
    var div = document.querySelectorAll('div');
    div[0].onclick = function () {
      alert('1')
      // 传统方式删除事件
      div[0].onclick = null;
    }

    div[1].addEventListener('click', fn)//这个fn调用不用加小括号
		//方法监听注册方式删除事件
    function fn() {
      alert(2);
      // 放在里面可以点一次2
      div[1].removeEventListener('click', fn)
    }
        
  </script>
</body>

</html>
DOM事件流

事件流描述的是页面中就收事件的顺序。

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

代码验证

https://www.bilibili.com/video/BV1k4411w7sV?p=62

在这里插入图片描述

在这里插入图片描述

事件对象
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    div{
      width: 100px;
      height: 100px;
      margin: 100px auto;
      background-color: crimson;
    }
  </style>
</head>
<body>
  <div>123</div>
  <script>
    var div = document.querySelectorA('div');
    div.onclick = function(event){
      // 1.event 就是一个事件对象 写到监听函数的小括号里面 当形参看
      // 2.事件对象只有 有了事件才会存在 他是系统自动创建的,不需要传递参数
      // 3.事件对象是 我们事件一系列相关数据的集合比如鼠标点击里面就包含了鼠标的相关信息,鼠标坐标啊,如果是键盘事件里面就包含的键盘事件的信息 比如 判断用户按下了哪个键?
      //事件对象自己命名 
      // 事件对象有兼容性问题 ie678 浏览器不会给方法传递参数  通过 window.event 
      // 兼容性处理方法  
        e = e || window.event
      // 现在一般不用处理 所以上面的兼容性问题不用写
        console.log(event);   
    }
  </script>
</body>
</html>

在这里插入图片描述

this 和 e.target 的区别

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    div {
      width: 100px;
      height: 100px;
      background-color: chocolate;
    }
  </style>
</head>

<body>
  <!-- this 和 target 的区别 -->
  <div>123</div>
  <ul>
    <li>abc</li>
    <li>abc</li>
    <li>abc</li>
  </ul>
  <script>
    // 常见事件对象的属性和方法
    // e.target 返回的是触发事件的对象(元素)  this 返回的是绑定事件的对象(元素)
    // 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 (eve) {
      // 我们给 ul 绑定了事件 那么this指向的就是ul
      console.log(this);
      // eve.target 指向了我们点击的那个对象 谁触发了事件我们就指向谁 我们点击的是li那么eve.target指向的就是li
      console.log(eve.target);


    })
  </script>
</body>

</html>
阻止事件冒泡

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
    <style>
      .father{
        width: 400px;
        height: 400px;
        margin: 100px auto;
        background-color: coral;
        position: relative;
        border-radius: 20px;

      }
      .son{
        width: 300px;
        height: 300px;
        background-color: crimson;      
        border-radius: 20px;
        text-align: center;
        line-height: 300px;
        position:absolute;
        left: 50px;
        top: 50px;
      }
    </style>
</head>
<body>
    <div class="father">
      <div class="son">son</div>
    </div>
    <script>
      // 阻止冒泡 DOM 推荐的标准 stopPropagation()
      var son = document.querySelector('.son');
      son.addEventListener('click',function(e){
        alert('son');

        e.stopPropagation();//stop 停止 Propagation传播
        //非标准ie 兼容  cancel 取消 Bubble泡泡
        // e.cancelBubble = true;
      },false)

      var father = document.querySelector('.father');
      father.addEventListener('click',function(e){
        alert('father');
      },false)
      document.addEventListener('click',function(e){
        alert('document');
      },false)
    </script>
</body>
</html>
事件委托(代理、委派)

事件委托原理:

​ 不要个每一个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用

冒泡原理影响设置每一个子节点。

作用:

​ 只操作了一次DOM,提高程序性能。

<!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>
  <ul>
    <li>点击弹框</li>
    <li>点击弹框</li>
    <li>点击弹框</li>
    <li>点击弹框</li>
    <li>点击弹框</li>
  </ul>
  <script>
    // 事件委托原理:给父节点添加监听器,利用事件冒泡影响每一个子节点
    var ul = document.querySelector('ul');
    ul.addEventListener('click',function(event){
      alert('弹框来了');
      // event.target 可以获得点击的对象  点击的是li 所以可以操作li
      event.target.style.backgroundColor = 'pink';
    })
  </script>
</body>
</html>
常用的鼠标事件对象

在这里插入图片描述

禁止选中文字和禁止右键菜单
<!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>
  <p>你选不到我</p>
  <script>
    // 1.禁止鼠标右键菜单     
    // contextmenu 主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
    var p = document.querySelector('p');
    p.addEventListener('contextmenu',function(e){
      //preventDefault() 方法  取消事件的默认动作。
      e.preventDefault();
    })
    // 2. 禁止鼠标选中  (selectstart  开始选中)   
    p.addEventListener('selectstart',function(e){
      //preventDefault() 方法  取消事件的默认动作。
      e.preventDefault();
    })
  </script>
</body>
</html>
获取鼠标坐标
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body{
      height: 1000px;
    }
  </style>
</head>
<body>
  <script>
    document.addEventListener('click',function(event){
      // client 鼠标在可视区域的x和y坐标
      console.log(event.clientX);
      console.log(event.clientY);
      console.log('---------------------------');
      
      // page  鼠标在页面文档的x和y坐标 ie9+支持
      console.log(event.pageX);
      console.log(event.pageY);
    })
  </script>
</body>
</html>
小黑猫鼠标跟随案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        img{
            width: 30px;
            position: absolute;
        }
    </style>
</head>
<body>
    <img src="../../img/angel.gif" alt="">
    <script>
        var pic = document.querySelector('img');
        document.addEventListener('mousemove',function(e){
            // 1.mousemove 鼠标移动1px 就触发这个事件
            // 每次移动鼠标可以得到鼠标最新的x和y 的坐标 (x,y) 和gif图的top和left绑定就可以得到鼠标跟随效果
            var x = e.pageX;
            var y = e.pageY;
            // console.log('x坐标:'+x+'y坐标:'+y);
            // 不要忘记给top 和left 加上单位px
            pic.style.left = (x-15) + 'px';
            pic.style.top = (y-15)+ 'px';
        })
    </script>
</body>
</html> 
常用键盘事件

在这里插入图片描述

<!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>
    <script>
      // 常用键盘事件
      // 1.keyup 按键弹起时候触发
      document.addEventListener('keyup',function(){
        console.log('弹起了');       
      })
      // keydown 按键按下时触发
      document.addEventListener('keydown',function(){
        console.log('按下了');       
      })
      // keypress 按键按下时触发 不识别功能按键,例如ctrl shift 箭头等
      document.addEventListener('keypress',function(){
        console.log('按下了keypress');       
      })

  // 三个事件的执行顺序 keydown→ keypress→keyup
    </script>
</body>
</html>
键盘事件对象

keyCode返回按键ASCII码值

<!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>
  <script>
    // 键盘事件对象中的keyCode属性可以得到响应你就按的ASCII码值
    document.addEventListener('keyup',function(event){
      console.log(event.keyCode)
      // keyup  和 keydown 事件不区分大小写 ASCII码值一样 
      // keypress 不识别功能键但是区分大小写
    })
  </script>
</body>
</html>
模拟京东按键输入内容案例
<!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>
    <!-- 
        核心思路:检查用户是否按下了s键,如果按下s键,就把光标定位到搜索框里面
        使用键盘事件对象里面的keyCode 判断用户按下的是否是s键
        搜索框获得焦点 :使用js里面的focus() 方法
     -->

     <input type="text">
     <script>
         var search =document.querySelector('input');
         document.addEventListener('keyup',function(event){
            // console.log(event.keyCode)
             if(event.keyCode === 83){
                 search.focus();
             }
            
         })
     </script>
</body>
</html>
模拟京东快递单号查询案例
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://at.alicdn.com/t/font_1906337_4q3wee1ox1s.css">
    <title>Document</title>
    <style>
        body {
            /* background-color: salmon; */
        }

        .search {
            width: 200px;
            height: 100px;
            /* background-color: cornflowerblue; */
            margin: 100px auto;
            position: relative;
        }

        .con {
            box-shadow: 1px 1px 5px 1px #ebeaea;
            /* box-shadow: -1px 1px 3px 1px #c7c3c3 ; */
            border: darkgray 1px solid;
            margin-bottom: 10px;
            font-size: 25px;
            z-index: 1;
            display: none;
            text-shadow: 0px 1px 0px #afaeae;

        }

        i {
            position: absolute;
            font-size: 20px;
            left: 9px;
            top: 24px;
            color: #ffffff;
            text-shadow: 1px 2px 1px #afaeae;
            z-index: 1;
            display: none;
        }

        input {
            /* position: absolute; */
        }
    </style>
</head>

<body>
    <div class="search">
        <i class="icon-icon2 iconfont"></i>
        <div class="con">

        </div>
        <input type="text" placeholder="请输入快递单号" id="jd" value="">
    </div>
    <script>
        // 输入内容时,上面的大号字体盒子(con)显示
        // 表单检测用户输入:给表单添加键盘事件
        // 同时把快递单号里面的值(valve)获取过来赋值给 con盒子(innerHTML)作为内容
        // 如果快递单号的内容为空,则隐藏大号字体盒子con
        var con = document.querySelector('.con');
        // console.log(con);

        var input = document.getElementById('jd')
        // console.log(input);
        var i = document.querySelector('i')
        // 这里用keyup 不用keydown 和keypress的原因是因为 他们两个事件触发时候,文字还没落入文本框

        input.addEventListener('keyup', function () {
            if (this.value == '') {
                con.style.display = 'none';
                i.style.display = 'none';
            } else {
                con.innerHTML = this.value;
                con.style.display = 'block';
                i.style.display = 'block';
            }

        })
    </script>
</body>

</html>

up’,function(event){
// console.log(event.keyCode)
if(event.keyCode === 83){
search.focus();
}

     })
 </script>
```
模拟京东快递单号查询案例
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://at.alicdn.com/t/font_1906337_4q3wee1ox1s.css">
    <title>Document</title>
    <style>
        body {
            /* background-color: salmon; */
        }

        .search {
            width: 200px;
            height: 100px;
            /* background-color: cornflowerblue; */
            margin: 100px auto;
            position: relative;
        }

        .con {
            box-shadow: 1px 1px 5px 1px #ebeaea;
            /* box-shadow: -1px 1px 3px 1px #c7c3c3 ; */
            border: darkgray 1px solid;
            margin-bottom: 10px;
            font-size: 25px;
            z-index: 1;
            display: none;
            text-shadow: 0px 1px 0px #afaeae;

        }

        i {
            position: absolute;
            font-size: 20px;
            left: 9px;
            top: 24px;
            color: #ffffff;
            text-shadow: 1px 2px 1px #afaeae;
            z-index: 1;
            display: none;
        }

        input {
            /* position: absolute; */
        }
    </style>
</head>

<body>
    <div class="search">
        <i class="icon-icon2 iconfont"></i>
        <div class="con">

        </div>
        <input type="text" placeholder="请输入快递单号" id="jd" value="">
    </div>
    <script>
        // 输入内容时,上面的大号字体盒子(con)显示
        // 表单检测用户输入:给表单添加键盘事件
        // 同时把快递单号里面的值(valve)获取过来赋值给 con盒子(innerHTML)作为内容
        // 如果快递单号的内容为空,则隐藏大号字体盒子con
        var con = document.querySelector('.con');
        // console.log(con);

        var input = document.getElementById('jd')
        // console.log(input);
        var i = document.querySelector('i')
        // 这里用keyup 不用keydown 和keypress的原因是因为 他们两个事件触发时候,文字还没落入文本框

        input.addEventListener('keyup', function () {
            if (this.value == '') {
                con.style.display = 'none';
                i.style.display = 'none';
            } else {
                con.innerHTML = this.value;
                con.style.display = 'block';
                i.style.display = 'block';
            }

        })
    </script>
</body>

</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值