文章目录

  • DOM基础
  • DOM 简介
  • 获取元素
  • 事件基础
  • 事件三要素
  • 执行事件的步骤
  • 操作元素
  • 操作节点
  • DOM重点核心
  • 事件高级
  • 注册事件
  • 解绑事件
  • DOM事件流
  • 事件对象
  • 阻止事件冒泡
  • 事件委托(代理、委派)
  • 7. 常用的鼠标事件
  • 键盘事件
  • ROM



MDN文档链接:

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


黑马springcloud笔记码源 黑马前端笔记_html

DOM基础

DOM 简介

文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。 W3C 已经定义了一系列的 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式。

黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_02

获取元素

因为文档页面从上往下加载,所以先要写标签,script要写到标签下面
根据 ID 获取
getElementById() 方法,返回带有 ID 的元素对象。
document.getElementById(‘id’);

console.dir() 可以打印我们获取的元素对象,更好的查看对象里面的属性和方法。

<body>
    <div id="time">2022-8-30</div>
    <script>
        // 因为文档页面从上往下加载,所以先要写标签,script要写到标签下面
        var timer=document.getElementById('time');
        console.log(timer);
        console.log(typeof timer);//返回的是一个对象
        console.dir(timer);
    </script>
</body>

黑马springcloud笔记码源 黑马前端笔记_前端_03


根据标签名获取

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

document.getElementsByTagName(‘标签名’);

注意:

  1. 因为得到的是一个对象的集合,所以我们想要操作里面的元素就需要遍历。
  2. 得到元素对象是动态的
  3. 返回的是元素对象的伪数组,如果页面中没有该元素,返回的是空的伪数组。
<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);
        console.log(lis[0]);
        //遍历元素
        for(var i=0;i<lis.length;i++){
            console.log(lis[i]);
        }
    </script>
</body>

黑马springcloud笔记码源 黑马前端笔记_前端_04


获取父元素内部的指定标签名的子元素

注意:父元素必须是一个指定的元素

<body>
    <ul>
        <li>这是一个标签1</li>
        <li>这是一个标签2</li>
        <li>这是一个标签3</li>
        <li>这是一个标签4</li>
        <li>这是一个标签5</li>
    </ul>
    <ol id="ol">
        <li>1234567</li>
        <li>1234567</li>
        <li>1234567</li>
    </ol>
    <script>
        var ol=document.getElementsByTagName('ol');
        console.log(ol[0].getElementsByTagName('li'));//必须指明哪一个元素
        var ol1=document.getElementById('ol');
        console.log(ol1.getElementsByTagName('li'));
    </script>
</body>
  • document.getElementsByClassName(‘类名’);根据类名返回元素对象集合
  • document.querySelector(‘选择器’); 根据指定选择器返回第一个元素对象
    根据类名class选择,加 “ . ” ,根据id选择,加 “ # ” ,根据标签选择,不用加
  • document.querySelectorAll(‘选择器’); 根据指定选择器返回所有对象
<body>
    <div class="box">盒子</div>
    <div class="box">盒子</div>
    <div id="nav">
        <ul>
            <li>产品</li>
            <li>首页</li>
        </ul>
    </div>
    <script>
        // getElementsByClassName(‘类名’) 根据类名返回元素对象集合
        var boxes=document.getElementsByClassName('box');
        console.log(boxes);
        // document.querySelector('选择器')  根据指定选择器返回第一个元素对象
        var firstBox=document.querySelector('.box');//根据class选择
        console.log(firstBox);
        var nav=document.querySelector('#nav');//根据id选择
        console.log(nav);
        var li=document.querySelector('li');//根据标签选择
        console.log(li);
        // document.querySelectorAll('选择器')  根据指定选择器返回
        var allBox=document.querySelectorAll('.box');
        console.log(allBox);
    </script>
</body>

黑马springcloud笔记码源 黑马前端笔记_javascript_05


黑马springcloud笔记码源 黑马前端笔记_javascript_06

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // 获取body元素
        var bodyEle=document.body;
        console.log(bodyEle);
        console.dir(bodyEle);
        // 获取html元素
        var htmlEle=document.documentElement;
        console.log(htmlEle);
    </script>
</body>
</html>

黑马springcloud笔记码源 黑马前端笔记_javascript_07

事件基础

黑马springcloud笔记码源 黑马前端笔记_前端_08

事件三要素
  1. 事件源 (谁)
  2. 事件类型 (什么事件)
  3. 事件处理程序 (做啥)

示例:

<body>
    <!-- 点击一个按钮,弹出对话框 -->
    <button id="btn">唐伯虎</button>
    <script>
        var btn=document.getElementById('btn');//获取事件源
        // 事件类型,如何触发事件      
        // 事件处理程序 通过一个函数赋值的方式完成
        btn.onclick=function(){
            alert('点秋香');
        }
    </script>
</body>
执行事件的步骤
  1. 获取事件源
  2. 注册事件(绑定事件)
  3. 添加事件处理程序(采取函数赋值形式)

示例:

<body>
    <div>123</div>
    <script>
        var div=document.querySelector('div');//获取事件源
        //注册事件,添加事件处理程序
        div.onclick=function(){
            console.log('我被选中了');
        }
    </script>
</body>

黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_09

操作元素

黑马springcloud笔记码源 黑马前端笔记_html_10

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div,
        p {
            width: 300px;
            height: 30px;
            line-height: 30px;
            color: #fff;
            background-color: blue;
        }
    </style>
</head>

<body>
    <button>显示当前系统时间</button>
    <div>某个时间</div>
    <p>1123</p>
    <script>
        var btn=document.querySelector('button');
        var div=document.querySelector('div');
        btn.onclick=function(){
            div.innerText= getDate();
        }
        function getDate() {
            var date=new Date();
            var year=date.getFullYear();
            var month=date.getMonth();
            var dates=date.getDate();
            var day=date.getDay();
            var arr=['星期日','星期一','星期二','星期三','星期四','星期五','星期六'];
            return '今天是:'+year+'年'+month+'月'+dates+'日,本周'+arr[day];
        }
        var p=document.querySelector('p');
        p.innerText=getDate();//可以不用添加事件
    </script>
</body>
</html>

黑马springcloud笔记码源 黑马前端笔记_html_11


innerText 和 innerHTML 的区别

  1. innerText不识别 html标签;innerHTML 可以识别
<body>
    <div></div>
    <script>
        var div=document.querySelector('div');
        div.innerText='<strong>今天是:</strong>2019';
        div.innerHTML='<strong>今天是:</strong>2019';
    </script>
</body>

黑马springcloud笔记码源 黑马前端笔记_前端_12


黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_13


2. 两个属性都可以可以获取元素里的内容,innerText 会去除换行和空格;innerHTML 保留空格和换行。

<body>
    <div></div>
    <p>
        我是文字
        <span>
            123
        </span>
    </p>
    <script>
        // 可以获取元素里的内容
        var p=document.querySelector('p');
        console.log(p.innerText);
        console.log(p.innerHTML);
    </script>
</body>

黑马springcloud笔记码源 黑马前端笔记_前端_14


黑马springcloud笔记码源 黑马前端笔记_前端_15


格式:元素.属性=赋值;

案例:点击切换图片

<body>
    <button id="ldh">刘德华</button>
    <button id="zxy">张学友</button> <br>
    <img src="images/ldh.jpg" alt="" title="刘德华">
    <script>
        // 修改元素属性 src
        var ldh=document.getElementById('ldh');
        var zxy=document.getElementById('zxy');
        var img=document.querySelector('img');
        zxy.onclick=function(){
            img.src='images/zxy.jpg';
            img.title='张学友';
        }
        ldh.onclick=function(){
            img.src="images/ldh.jpg";
            img.title='刘德华';
        }
    </script>
</body>

黑马springcloud笔记码源 黑马前端笔记_javascript_16

<body>
    <button>按钮</button>
    <input type="text" value="输入内容">
    <script>
        var btn=document.querySelector('button');
        var input=document.querySelector('input');
        btn.onclick=function(){
            input.value='被点击了';
            // btn.disabled=true;  也可写作:
            this.disabled=true;
            // this指向的是时间函数的调用者(按钮)
        }
    </script>
</body>

黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_17


黑马springcloud笔记码源 黑马前端笔记_前端_18


案例:点击修改元素颜色和大小

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{
            width: 200px;
            height: 200px;
            background-color: aqua;
        }
    </style>
</head>
<body>
    <div></div>
    <script>
        var div=document.querySelector('div');
        div.onclick=function(){
            this.style.backgroundColor='purple';
            this.style.width='400px';
        }
    </script>
</body>
</html>

黑马springcloud笔记码源 黑马前端笔记_javascript_19


黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_20


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

黑马springcloud笔记码源 黑马前端笔记_前端_21


黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_22


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

示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{
            margin: 50px;
            width: 400px;
            height: 200px;
            background-color: pink;
        }
        .change{
            background-color:blueviolet;
            color: #fff;
            font-size: 25px;
            margin-top: 200px;
        }
    </style>
</head>
<body>
    <div>文本内容</div>
    <script>
        var test=document.querySelector('div');
        test.onclick=function(){
            this.className='change';
        }
    </script>
</body>
</html>

黑马springcloud笔记码源 黑马前端笔记_前端_23


黑马springcloud笔记码源 黑马前端笔记_前端_24


在上面的例子中,如果想要保留原来的类名,可以:

<script>
    var test=document.querySelector('div');
    test.onclick=function(){
        // this.className='change';
        this.className='first change';
    }
</script>

黑马springcloud笔记码源 黑马前端笔记_html_25


黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_26


案例:被点到的按钮背景颜色变红

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        button{
            margin-top: 100px;
        }
    </style>
</head>
<body>
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <button>按钮4</button>
    <button>按钮5</button>
    <script>
        var btn=document.querySelectorAll('button');
        for(var i=0;i<btn.length;i++){
            btn[i].onclick=function(){
                console.log(this.innerHTML);
                for(var i=0;i<btn.length;i++){
                    btn[i].style.backgroundColor=''
                }
                this.style.backgroundColor='pink';
            }
        }
    </script>
</body>
</html>

黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_27


黑马springcloud笔记码源 黑马前端笔记_html_28


黑马springcloud笔记码源 黑马前端笔记_html_29


黑马springcloud笔记码源 黑马前端笔记_选择器_30

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="demo" index="1" class="nav"></div>
    <script>
        var div=document.querySelector('div');
        // 获取元素属性值
        // element.属性
        console.log(div.id);
        // element.getAttribute('属性');
        console.log(div.getAttribute('id'));
        // 两种方法的区别
        // element.属性获取的是元素自带的内置属性值
        // element.getAttribute('属性')可以获得自定义的属性
        console.log(div.getAttribute('index'));
        // 2. 设置元素属性值
        // (1) element.属性= '值'
        div.id='test';
        div.className='navs';
        // (2) element.setAttribute('属性', '值');  主要针对于自定义属性
        div.setAttribute('index',2);
        div.setAttribute('class','footer');
        div.removeAttribute('index');//移除属性
    </script>
</body>
</html>

黑马springcloud笔记码源 黑马前端笔记_javascript_31

<body>
    <div getTime="20" data-index="2" data-list-name="andy"></div>
    <script>
        var div=document.querySelector('div');
        console.log(div.getAttribute('getTime'));
        console.log(div.getAttribute('data-list-name'));
        div.setAttribute('data-time',20);
        // h5新增的获取自定义属性的方法 它只能获取data-开头的
        // dataset 是一个集合里面存放了所有以data开头的自定义属性
        console.log(div.dataset);
        console.log(div.dataset.index);
        console.log(div.dataset['index']);
        // 如果自定义属性里面有多个-链接的单词,我们获取的时候采取 驼峰命名法
        console.log(div.dataset.listName);
        console.log(div.dataset['listName']);
    </script>
</body>

黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_32

操作节点

黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_33


黑马springcloud笔记码源 黑马前端笔记_javascript_34


黑马springcloud笔记码源 黑马前端笔记_选择器_35

<body>
    <!-- 节点的优点 -->
    <div class="box">
        <span class="erweima">×</span>
    </div>
    <script>
        var box=document.querySelector('.box');
        console.dir(box);
    </script>
</body>

黑马springcloud笔记码源 黑马前端笔记_选择器_36


黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_37


黑马springcloud笔记码源 黑马前端笔记_选择器_38

<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">×</span>
        </div>
    </div>
    <script>
        // 以前的写法
        var erweima=document.querySelector('.erweima');
        var box=document.querySelector('.box');
        // 通过子节点获取父节点
        //得到的是离元素最近的父级节点,如果找不到父节点就返回为 null
        console.log(erweima.parentNode);
    </script>
</body>

黑马springcloud笔记码源 黑马前端笔记_前端_39

<body>
    <!-- 节点的优点 -->
    <div>我是div</div>
    <span>我是span</span>
    <ul>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
    </ul>
    <ol>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
    </ol>

    <div class="demo">
        <div class="box">
            <span class="erweima">×</span>
        </div>
    </div>
    <script>
        // 以前的写法
        var ul=document.querySelector('ul');
        var lis=ul.querySelectorAll('li');
        // 获取父节点的子节点 所有的子节点 包含 元素节点 文本节点等等
        console.log(ul.childNodes);
        // 筛选元素节点 nodeType
        console.log(ul.childNodes[0].nodeType);
        console.log(ul.childNodes[1].nodeType);
        for(var i=0;i<ul.childNodes.length;i++){
            if(ul.childNodes[i].nodeType==1){
                //判断 ul.childNodes[i] 是否是元素节点
                console.log(ul.childNodes[i]);
            }
        }
        // 获取子元素节点更简单的方法
        //children 获取所有的子元素节点 也是我们实际开发常用的
        console.log(ul.children);
    </script>
</body>

黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_40


console.log(ul.childNodes);的返回值有9个元素,是因为文本节点也会被返回。

黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_41


黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_42

<ol>
    <li>我是li1</li>
    <li>我是li2</li>
    <li>我是li3</li>
    <li>我是li4</li>
    <li>我是li5</li>
</ol>
<script>
    var ol=document.querySelector('ol');
    // 1. firstChild 第一个子节点 不管是文本节点还是元素节点
    console.log(ol.firstChild);//返回的是一个文本节点
    console.log(ol.lastChild);//返回的是一个文本节点
    // 2. firstElementChild 返回第一个子元素节点 ie9才支持
    console.log(ol.firstElementChild);
    console.log(ol.lastElementChild);
    // 3. 实际开发的写法  既没有兼容性问题又返回第一个子元素
    console.log(ol.children[0]);
    console.log(ol.children[ol.children.length-1]);
</script>

黑马springcloud笔记码源 黑马前端笔记_html_43


黑马springcloud笔记码源 黑马前端笔记_html_44

<body>
    <div>我是div</div>
    <span>我是span</span>
    <script>
        var div=document.querySelector('div');
        // 1.nextSibling 下一个兄弟节点 包含元素节点或者 文本节点等等
        console.log(div.nextSibling);
        console.log(div.previousSibling);
        // 2. nextElementSibling 得到下一个兄弟元素节点
        console.log(div.nextElementSibling);
        console.log(div.previousElementSibling);
    </script>
</body>

黑马springcloud笔记码源 黑马前端笔记_javascript_45


黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_46


黑马springcloud笔记码源 黑马前端笔记_前端_47


黑马springcloud笔记码源 黑马前端笔记_html_48

<ul>
<li>123</li>
</ul>
<script>
// 1. 创建节点元素节点
var li = document.createElement('li');
/* 2. 添加节点 node.appendChild(child)  node 父级  child 是子级 
后面追加元素  类似于数组中的push */
var ul = document.querySelector('ul');
ul.appendChild(li);
// 3. 添加节点 node.insertBefore(child, 指定元素);
var lili = document.createElement('li');
lili.innerHTML='lili';
ul.insertBefore(lili, ul.children[0]);
// 4. 我们想要页面添加一个新的元素 : 1. 创建元素 2. 添加元素
</script>

黑马springcloud笔记码源 黑马前端笔记_javascript_49


黑马springcloud笔记码源 黑马前端笔记_前端_50

<body>
    <button>删除</button>
    <ul>
        <li>熊大</li>
        <li>熊二</li>
        <li>光头强</li>
    </ul>
    <script>
        // 1.获取元素
        var ul = document.querySelector('ul');
        var btn = document.querySelector('button');
        // 2. 删除元素  node.removeChild(child)
        // ul.removeChild(ul.children[0]);
        // 3. 点击按钮依次删除里面的孩子
        btn.onclick = function() {
            if (ul.children.length == 0) {
                this.disabled = true;
            } else {
                ul.removeChild(ul.children[0]);
            }
        }
    </script>
</body>

黑马springcloud笔记码源 黑马前端笔记_html_51

<ul>
    <li>1111</li>
    <li>2</li>
    <li>3</li>
</ul>
<script>
    var ul = document.querySelector('ul');
    // 1. node.cloneNode(); 括号为空或者里面是false 浅拷贝 只复制标签不复制里面的内容
    // 2. node.cloneNode(true); 括号为true 深拷贝 复制标签复制里面的内容
    var lili = ul.children[0].cloneNode(true);
    ul.appendChild(lili);
</script>

黑马springcloud笔记码源 黑马前端笔记_javascript_52

  • document.write() 创建元素 如果页面文档流加载完毕, 再调用这句话会导致页面重绘,原先的页面内容会丢失
  • innerHTML,通过拼接字符串的方式效率较低,建议采用数组形式

<body>
    <button>点击</button>
    <p>abc</p>
    <div class="inner"></div>
    <div class="create"></div>
    <script>
        // window.onload = function() {
        //         document.write('<div>123</div>');

        //     }
        // 三种创建元素方式区别 
         /* 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 <= 100; i++) {
        //     inner.innerHTML += '<a href="#">百度</a>'
        // }通过拼接字符串的方式,速度较慢
        var arr = [];
        for (var i = 0; i <= 100; i++) {
            arr.push('<a href="#">百度</a>');
        }
        inner.innerHTML = arr.join('');
        // 3. document.createElement() 创建元素
        var create = document.querySelector('.create');
        for (var i = 0; i <= 100; i++) {
            var a = document.createElement('a');
            create.appendChild(a);
        }
    </script>
</body>

innerHTML字符串拼接效率测试

<script>
    function fn() {
        var d1 = +new Date();

        var str = '';
        for (var i = 0; i < 1000; i++) {
            document.body.innerHTML += '<div style="width:100px; height:2px; border:1px solid blue;"></div>';
        }
        var d2 = +new Date();
        console.log(d2 - d1);
    }
    fn();
</script>

innerHTML数组效率测试

<script>
    function fn() {
        var d1 = +new Date();
        var array = [];
        for (var i = 0; i < 1000; i++) {
            array.push('<div style="width:100px; height:2px; border:1px solid blue;"></div>');
        }
        document.body.innerHTML = array.join('');
        var d2 = +new Date();
        console.log(d2 - d1);
    }
    fn();
</script>

createElement效率测试

<script>
    function fn() {
        var d1 = +new Date();

        for (var i = 0; i < 1000; i++) {
            var div = document.createElement('div');
            div.style.width = '100px';
            div.style.height = '2px';
            div.style.border = '1px solid red';
            document.body.appendChild(div);
        }
        var d2 = +new Date();
        console.log(d2 - d1);
    }
    fn();
</script>

DOM重点核心

黑马springcloud笔记码源 黑马前端笔记_前端_53


黑马springcloud笔记码源 黑马前端笔记_选择器_54


黑马springcloud笔记码源 黑马前端笔记_html_55


黑马springcloud笔记码源 黑马前端笔记_javascript_56


黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_57


黑马springcloud笔记码源 黑马前端笔记_选择器_58


黑马springcloud笔记码源 黑马前端笔记_前端_59


黑马springcloud笔记码源 黑马前端笔记_选择器_60

事件高级

注册事件

黑马springcloud笔记码源 黑马前端笔记_前端_61


黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_62


黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_63

<button>传统注册事件</button>
<button>方法监听注册事件</button>
<button>ie9 attachEvent</button>
<script>
    var btns = document.querySelectorAll('button');
    // 1. 传统方式注册事件
    btns[0].onclick = function() {
        alert('hi');
    }
    btns[0].onclick = function() {
            alert('hao a u');
        }
        // 2. 事件侦听注册事件 addEventListener 
        // (1) 里面的事件类型是字符串 必定加引号 而且不带on
        // (2) 同一个元素 同一个事件可以添加多个侦听器(事件处理程序)
    btns[1].addEventListener('click', function() {
        alert(22);
    })
    btns[1].addEventListener('click', function() {
            alert(33);
        })
</script>

黑马springcloud笔记码源 黑马前端笔记_javascript_64

解绑事件

黑马springcloud笔记码源 黑马前端笔记_javascript_65

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

   function fn() {
       alert(22);
       divs[1].removeEventListener('click', fn);
   }
</script>

黑马springcloud笔记码源 黑马前端笔记_javascript_66

DOM事件流

黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_67


黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_68


如果addEventListener 第三个参数是 true 那么则处于捕获阶段

如果addEventListener 第三个参数是 false 或者 省略 那么则处于冒泡阶段

捕获阶段:点击(事件发生)son时会先执行father的事件处理函数,再执行son的事件处理函数,事件向下传播

冒泡阶段:点击(事件发生)son时会先执行son的事件处理函数,再执行father的事件处理函数,事件向上传播

<div class="father">
  	<div class="son">son盒子</div>
</div>
<script>
  // dom 事件流 三个阶段
  // 1. JS 代码中只能执行捕获或者冒泡其中的一个阶段。
  // 2. onclick 和 attachEvent(ie) 只能得到冒泡阶段。
  // 3. 捕获阶段 如果addEventListener 第三个参数是 true 那么则处于捕获阶段 
  // document -> html -> body -> father -> son
  // var son = document.querySelector('.son');
  // son.addEventListener('click', function() {
  //     alert('son');
  // }, true);
  // var father = document.querySelector('.father');
  // father.addEventListener('click', function() {
  //     alert('father');
  // }, true);
  // 4. 冒泡阶段 如果addEventListener 第三个参数是 false 或者 省略 那么则处于冒泡阶段  
  //son -> father ->body -> html -> document
	  var son = document.querySelector('.son');
	  son.addEventListener('click', function() {
	      alert('son');
	  }, false);
	  var father = document.querySelector('.father');
	  father.addEventListener('click', function() {
	      alert('father');
	  }, false);
	  document.addEventListener('click', function() {
	      alert('document');
	  })
</script>

事件对象

黑马springcloud笔记码源 黑马前端笔记_前端_69


黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_70


黑马springcloud笔记码源 黑马前端笔记_html_71

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

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

黑马springcloud笔记码源 黑马前端笔记_html_72


e.target 返回的是触发事件的对象(元素)

this 返回的是绑定事件的对象(元素)

区别 : e.target 点击了那个元素,就返回那个元素

this 那个元素绑定了这个点击事件,那么就返回谁

<div>123</div>
<ul>
    <li>abc</li>
    <li>abc</li>
    <li>abc</li>
</ul>
<script>
    /* 1. 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(e) {
            // 我们给ul 绑定了事件  那么this 就指向ul  
            console.log(this);
            console.log(e.currentTarget);
            // e.target 指向我们点击的那个对象 谁触发了这个事件 
            // 触发事件的是li,因为冒泡,所以事件被ul捕获并执行事件处理函数
            // 我们点击的是li e.target 指向的就是li
            console.log(e.target);
        })
        // 了解兼容性
        // div.onclick = function(e) {
        //     e = e || window.event;
        //     var target = e.target || e.srcElement;
        //     console.log(target);
    // }
    // 2. 了解 跟 this 有个非常相似的属性 currentTarget  ie678不认识
</script>

黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_73


e.type:返回事件类型

阻止默认行为(事件) 如:让链接不跳转 或者让提交按钮不提交

普通浏览器: e.preventDefault(); 方法

低版本浏览器: ie678 returnValue 属性

我们可以利用 return false 也能阻止默认行为 没有兼容性问题 ,特点: return 后面的代码不执行了, 而且只限于传统的注册方式

<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');
    div.addEventListener('click', fn);
    div.addEventListener('mouseover', fn);
    div.addEventListener('mouseout', fn);
    function fn(e) {
        console.log(e.type);
    }
    // 2. 阻止默认行为(事件) 让链接不跳转 或者让提交按钮不提交
    var a = document.querySelector('a');
    a.addEventListener('click', function(e) {
            e.preventDefault(); //  dom 标准写法
        })
        // 3. 传统的注册方式
    a.onclick = function(e) {
        // 普通浏览器 e.preventDefault();  方法
        // e.preventDefault();
        // 低版本浏览器 ie678  returnValue  属性
        // e.returnValue;
        // 我们可以利用return false 也能阻止默认行为 没有兼容性问题 
        // 特点: return 后面的代码不执行了, 而且只限于传统的注册方式
        return false;
        alert(11);
    }
</script>

阻止事件冒泡

黑马springcloud笔记码源 黑马前端笔记_前端_74

<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 传播
        e.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡
    }, false);

    var father = document.querySelector('.father');
    father.addEventListener('click', function() {
        alert('father');
    }, false);
    document.addEventListener('click', function() {
        alert('document');
    })
</script>

事件委托(代理、委派)

黑马springcloud笔记码源 黑马前端笔记_前端_75


黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_76


黑马springcloud笔记码源 黑马前端笔记_html_77

<ul>
    <li>知否知否,点我应有弹框在手!</li>
    <li>知否知否,点我应有弹框在手!</li>
    <li>知否知否,点我应有弹框在手!</li>
    <li>知否知否,点我应有弹框在手!</li>
    <li>知否知否,点我应有弹框在手!</li>
</ul>
<script>
    // 事件委托的核心原理:给父节点添加侦听器, 利用事件冒泡影响每一个子节点
    var ul = document.querySelector('ul');
    ul.addEventListener('click', function(e) {
        // alert('知否知否,点我应有弹框在手!');
        // e.target 这个可以得到我们点击的对象
        e.target.style.backgroundColor = 'pink';
    })
</script>

7. 常用的鼠标事件

黑马springcloud笔记码源 黑马前端笔记_选择器_78


黑马springcloud笔记码源 黑马前端笔记_选择器_79

<body>
    我是一段不愿意分享的文字
    <script>
        // 1. contextmenu 我们可以禁用右键菜单
        document.addEventListener('contextmenu', function(e) {
                e.preventDefault();
            })
            // 2. 禁止选中文字 selectstart
        document.addEventListener('selectstart', function(e) {
            e.preventDefault();
        })
    </script>
</body>

黑马springcloud笔记码源 黑马前端笔记_前端_80

  1. client 鼠标在可视区的x和y坐标,页面滚动条拖动后不会影响返回的坐标
  2. page 鼠标在页面文档的x和y坐标
  3. screen 鼠标在电脑屏幕的x和y坐标
<style>
        body {
            height: 3000px;
        }
    </style>
</head>

<body>
    <script>
        // 鼠标事件对象 MouseEvent
        document.addEventListener('click', function(e) {
            // 1. client 鼠标在可视区的x和y坐标,不管页面滚动条是否拖动
            console.log(e.clientX);
            console.log(e.clientY);
            console.log('---------------------');

            // 2. page 鼠标在页面文档的x和y坐标
            console.log(e.pageX);
            console.log(e.pageY);
            console.log('---------------------');

            // 3. screen 鼠标在电脑屏幕的x和y坐标
            console.log(e.screenX);
            console.log(e.screenY);

        })
    </script>
</body>

滚动前后点击屏幕同一位置

黑马springcloud笔记码源 黑马前端笔记_html_81


案例:

跟随鼠标移动的天使

案例分析

① 鼠标不断的移动,使用鼠标移动事件: mousemove

② 在页面中移动,给document注册事件

③ 图片要移动距离,而且不占位置,我们使用绝对定位即可

④ 核心原理: 每次鼠标移动,我们都会获得最新的鼠标坐标, 把这个x和y坐标做为图片的

top和left 值就可以移动图片

<style>
        img {
            position: absolute;
            top: 2px;
        }
    </style>
</head>

<body>
    <img src="images/angel.gif" alt="">
    <script>
        var pic = document.querySelector('img');
        document.addEventListener('mousemove', function(e) {
            // 1. mousemove只要我们鼠标移动1px 就会触发这个事件
            // console.log(1);
            // 2.核心原理: 每次鼠标移动,我们都会获得最新的鼠标坐标, 把这个x和y坐标做为图片的top和left 值就可以移动图片
            var x = e.pageX;
            var y = e.pageY;
            console.log('x坐标是' + x, 'y坐标是' + y);
            //3 . 千万不要忘记给left 和top 添加px 单位
            pic.style.left = x - 50 + 'px';
            pic.style.top = y - 40 + 'px';


        });
    </script>
</body>

键盘事件

黑马springcloud笔记码源 黑马前端笔记_前端_82

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

//     }
document.addEventListener('keyup', function() {
    console.log('我弹起了');
})

//3. keypress 按键按下的时候触发  不能识别功能键 比如 ctrl shift 左右箭头啊
document.addEventListener('keypress', function() {
        console.log('我按下了press');
    })
    //2. keydown 按键按下的时候触发  能识别功能键 比如 ctrl shift 左右箭头啊
document.addEventListener('keydown', function() {
        console.log('我按下了down');
    })
    // 4. 三个事件的执行顺序  keydown -- keypress -- keyup
</script>

黑马springcloud笔记码源 黑马前端笔记_黑马springcloud笔记码源_83

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

  1. 我们的keyup 和keydown事件不区分字母大小写 a 和 A 得到的都是65
  2. 我们的keypress 事件 区分字母大小写 a 97 和 A 得到的是65
<script>
    // 键盘事件对象中的keyCode属性可以得到相应键的ASCII码值
    // 1. 我们的keyup 和keydown事件不区分字母大小写  a 和 A 得到的都是65
    // 2. 我们的keypress 事件 区分字母大小写  a  97 和 A 得到的是65
    document.addEventListener('keyup',function(e){
        console.log(e);
        console.log('up:' + e.keyCode);
    })
    document.addEventListener('keypress',function(e){
        console.log('press:' + e.keyCode);
    })
</script>

黑马springcloud笔记码源 黑马前端笔记_javascript_84

ROM