笔记--DOM文档对象模型

1. DOM简介

在这里插入图片描述

2. 获取元素

(1). 根据标签名获取

    1. 根据标签名获取 :使用getElementsByTagName() 方法可以返回带有指定标签名的对象的集合。
    document.getElementsTagName('标签名');
     注意:
    	  1. 因为得到的是一个对象的集合,所以我们想要操作里面的元素就需要遍历
          2. 得到的元素是动态的
    2. 还可以获取某个元素(父元素)内部所有指定标签名的子元素。
    element.getElementsTagName('标签名');
    注意:父元素必须是单个对象(必须指明是哪一个元素对象).获取的时候不包括父元素自己
        // 1. 返回的是:获取过来元素对象的集合,以伪数组的形式存储
        var lis = document.getElementsTagName('li');
        console.log(lis);
        console.log(lis[0]);
        // 2. 我们想要依次打印里面的元素对象,我们可以采取遍历的方式
        for (var i = 0;i < lis.length; i++){
            console.log(lis[i]);
        }
        // 3. 如果页面只有一个li,返回的还是伪数组的形式
        // 4. 如果页面中没有这个元素,返回的是空的为数组的形式
        // var ol = document.getElementsTagName('ol'); //[ol]
        // console.log(ol[0].getElementsTagName('li'));
        var ol = document.getElementById('ol');
        console.log(ol.getElementsTagName('li'));

(2). 通过HTML5新增的方法获取

    1. document.getElementsByClassName('类名'); // 根据类名返回对象集合
    2. document.querySelector('选择器'); // 根据指定选择器返回第一个元素对象
    3. document.querySelectorAll('选择器'); // 根据指定选择器返回
        // 1. getElementsByClassName 根据类名获得某些元素集合
        var boxs = document.getElementsByClassName('box');
        console.log(boxs);
        // 2. querySelector 返回指定选择器的第一个元素对象,切记:里面的选择器需要加符号 .box #nav
        var firstBox = document.querySelector('.box');
        console.log(firstBox);
        var nav = document.querySelector('#nav');
        console.log(nav);
        var li = document.Selector('li');
        console.log(li);
        // 3. querySelectAll() 返回指定选择器的所有元素集合
        var allBox = document.querySelectorAll('.box');
        console.log(allBox);
        var lis = document.querySelectorAll('li');
        console.log(lis);

(3). 获取特殊元素(body, html)

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

3. 事件

(1). 执行事件的步骤

    1. 获取事件源
    2. 注册事件(绑定事件)
    3. 添加事件处理程序(采取函数赋值形式)
        // 执行鼠标事件步骤
        点击 div 控制台输出:我被选中了
        // 1. 获取事件源
        var div = document.querySelector('div');
        // 2. 绑定事件 注册事件
        // div.onclick
        // 3. 添加事件处理程序
        div.onclick = function() {
            console.log('我被选中了');
        }

(2). 常见的鼠标事件

在这里插入图片描述

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

4. 操作元素

(1). 改变元素内容

    element.innerText
    从起始位置到终止位置的内容,但它取出html标签,同时空格和换行也会去掉
    element.innerHTML
    起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行
        // 当我们点击了按钮,div里面的文字会发生变化
        // 1. 获取元素
        var btn = document.querySelector('button');
        var div = document.querySelector('div');
        // 2. 注册事件
        btn.onclick = function() {
            div,innerText = '2019-6-6';
        }
        // innerText 和 innerHTML 的区别
        // 1. innerText 不识别html标签 非标准 去除空格和换行
        var div = document.querySelector('div');
        // div.innerText = '<strong>今天是:</strong> 2019';
        // 2. innerHTNL 识别html 标签 W3C标准,保留空格和换行的
        div.innerHTML = '<strong>今天是:</strong> 2019';
        // 这两个属性是可读写的,可以获取元素里面的内容
        var p = document.querySelector('p');
        console.log(p.innerText);
        console.log(p.innerHTML);
	修改元素属性 src:
    <button id = "ldh">刘德华</button>
    <button id = "zxy">张学友</button>
    <img src="img/ldh.jpg" alt="" title="刘德华">
    <script>
        // 修改元素属性 src
        // 1. 获取元素
        var ldh = document.getElementById('#ldh');
        var zxy = document.getElementById('#zxy')
        var img = document.querySelector('img');
        // 2. 注册事件,处理程序
        zxy.onclivck = function() {
            img.src = 'img/zxy.jpg';
            img.title = '张学友';

        }
        ldh.onclik = function() {
            img.src = 'img/ldh.jpg';
            img.title = '刘德华';
        }
	禁用按钮disabled=true;
        // 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 指向的是事件函数的调用者 btn

        }

(2). 样式属性操作(焦点)

    我们可以通过js修改元素的大小,颜色,位置等样式。
    1. element.style  行内样式操作
    2. element.className  类名样式操作
    注意:
        1. js里面的样式采取驼峰命名法,比如:fontSize, backgroundColor
        2. js修改style样式操作,产生的是行内样式,css权重比较高
        3. 如果样式修改较多,可以采取类名方式更改元素样式
        4. class因为是保留字,因此使用classsName来操作元素类名属性
        5. className 会直接更改元素的类名,会覆盖原先的类名。
        // 焦点
        // 1. 获取元素
        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';
        }
	1. 使用element.style 获得修改元素样式,如果样式较少或者功能简单的情况下使用
	2. 通过修改元素的className更改元素的样式,适合于样式较多或者功能复杂的情况
	3. 如果想要保留原先的类名,我们可以这么做:多类名选择器
        // 1. 使用element.style 获得修改元素样式,如果样式较少或者功能简单的情况下使用
        var test = document.querySelector('div');
        test.onclick = function() {
            this.style.backgroundColor = 'purple';
            this.style.color = '#fff';
            this.style.fontSize = '25px';
            this.style.marginTop = '100px';

            // 让我们当前元素的类名改为change
            // 2. 通过修改元素的className更改元素的样式,适合于样式较多或者功能复杂的情况
            // 3. 如果想要保留原先的类名,我们可以这么做:多类名选择器
            // this.className = 'change';
            this.className = 'first change';
        }
        // 1. 获取元素
        var ipt = document.querySelector('.ipt');
        var message = document.querySelector('.message');
        // 2. 注册事件,失去焦点
        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.inner = '正确';
            }
        }

(3). 操作元素总结

在这里插入图片描述

(4). 排他思想

在这里插入图片描述

百度换肤
        // 百度换肤
        // 1. 获取元素
        var imgs = document.querySelector('.baidu').querySelectorAll('img');
        // 2. 循环注册事件
        for (var i = 0; i < imgs.length; i++) {
            imgs[i].onclick = function() {
                // this.src  就是我们点击图片的路径  images/2.jpg
                // console.log(this.src)
                // 把这个路径this.src 给body就可以了
                document.body.style.backgroundImage = 'url(' + this.src + ')';
            }
        }
勾选框初级
        <table border="1">
            <thead><td></td></thead>
            <tbody>
                <tr><td>1</td></tr>
                <tr><td>2</td></tr>
                <tr><td>3</td></tr>
            </tbody>
        </table>
        // 1. 获取元素
            var tbody = document.querySelector('tbody').querySelectorAll('tr');
        // 2. 循环注册事件
        for (var i = 0; i < tbody.length; i++) {
            console.log(tbody[i].onmouseover);
            tbody[i].onmouseover = function() {
                this.className = 'trs';
            }
            tbody[i].onmouseout = function() {
                this.className = '';
            }

        }
勾选框高级
        // 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;
            }
        }

(5). 自定义属性的操作

    1). 获取属性值

    element.属性   获得属性值
    element.getAttribute('属性');
    区别:
    	element.属性   获得内置属性值(元素本身自带的属性)
    	element.getAttribute('属性');  主要获得自定义属性(标准)我们程序员自定义的属性
      //  <div id = "demo" index = "1"></div>
      var div = document.querySelector('div');
      // 1. 获取元素的属性值
      // (1) element.属性
      console.log(div.id);
      // (2) element.getAttribute('属性');  get得到获取  attribute属性的意思
      // 我们程序员自己添加的属性,我们称为自定义属性 index
      console.log(div.getAttribute('id'));
      console.log(iv.getAttribute('index'));
      // 2. 设置元素属性值
      // (1) element.属性 = '值';
      div.id = 'test';
      div.className = 'navs';
      // (2) element.setArribute('属性','值'); 主要针对自定义属性
      div.setAttribute('index','2'); 
      div.setAttribute('class','footer'); // class特殊,这里面写的就是class,不是className
  2). 设置属性值
  element.属性 = '值';   设置内置属性值
  element.setAttribute('属性','值');
  区别:
  	element.属性    设置属性值
  	element.setAttribute('属性');  主要设置自定义属性

3). 移除属性
      // 3. 移除属性
      // 移除属性 removeAttribute(属性);
      div.removeAttribute('inex');

      // 干点所有人,其余的li清除class这个类
      for (var i = 0; i < lis.length; i++) {
          lis[i].className = '';
      }
      // 留下我自己
      this.className = 'current';
       //  下面的显示内容模块
      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';
4). H5自定义属性

在这里插入图片描述
在这里插入图片描述

      // <div getTime="20" data-index="2" data-list-name="andy"></div>
      var div = document.querySelector('div');
      // console.log(ddiv.getTime);
      console.log(div.getAttribute('getTime'));
      div.setAttribute('data-time',20);
      console.log(div.getAttribute('data-index'));
      console.log(div.getAttribute('data-list-name'));
      // 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']);

5. 节点操作

在这里插入图片描述
在这里插入图片描述

(1). 节点层级

1). 父级节点
    node.parentNode 
    parentNode属性可返回某节点的父节点,注意是最近的一个父节点
    如果指定的节点没有父节点则返回null
    // 1. 父节点 parentNode
    var bro = document.querySelector('.bro');
    // var box = document.querySelector('.box');
    console.log(bro.parentNode);
2). 子节点
    1. parentNode.childNodes(标准)
    	parentNode.childNodes返回指定节点的字节点的集合,该集合为即时更新的集合。
    	注意:返回值包含了所有子节点,包括元素节点,文本节点等。
    	如果只想要获得里面的元素节点,则需要专门处理,所以我们一般不提倡使用childNodes
	2. parentNode.children(非标准)
    	parentNode.children是一个只读属性,返回所有的子元素节点,其余节点不返回(重点)
    	虽然children是一个非标准,但是得到了各个浏览器的支持,因此我们可以放心使用
    var ul = document.querySelector('ul');
    for (var i = 0; i < ul.childNodes.length; i++) {
        if (ul.childNodes[i].nodeType == 1) {
            // ul.childNode[i]是元素节点
            console.log(ul.childNodes[i]);
        }
    }
3). DOM提供的方法(API)获取
    // DOM提供的方法(API)获取
    var ul = document.querySelector('ul');
    var lis = ul.querySelectorAll('li');
    // 1. 子节点childNodes所有字节点,包含:元素节点 文本节点等等
    console.log(ul.childNodes);
    console.log(ul.childNodes[0].nodeType);
    console.log(ul.childNodes[1].nodeType);
    // 2. children 获得所有的子元素节点,也是我们实际开发常用的
    console.log(ul.children);
4). parentNode.firstElementChild
		firstElementChild返回第一个子元素节点,找不到则返回null
5). parentNoe.lastElementChild
	    lastElementChild返回最后一个子元素节点,找不到返回null
	注意:这两个方法有兼容性问题,IE9以上才支持。
    var ol = document.querySelector('ol');
    // 1. firstChild第一个子节点,不管是文本节点还是元素节点
    console.log(ol.firstChild);
    console.log(ol.lastChild);
    // 2. firstElementChild返回第一个子元素节点
    console.log(ol.firstElementChild);
    console.log(ol.lastElementChild);
    // 3. 实际开发的写法,既没有兼容性问题又返回第一个子元素
    console.log(ol.children[0]);
    console.log(ol.children[ol.children.length-1]);
实例:下拉菜单
    // 1. 获取元素
    var nav = document.querySelector('.nav');
    var lis = nav.children; // 得到4个小li
    // 2. 循环注册事件
    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';
        }   
    }
6). 兄弟节点
    1. node.nextSibling
    	nextSibling返回当前元素的下一个兄弟节点,找不到则返回null,同样,也是包含所有节点
    2. node.previousSibling
    	previousSibling返回当前元素上一个兄弟节点,找不到则返回null,同样,也是包含所有节点
    3. node.nextElementSibling
    	nextElementSibling返回当前元素下一个兄弟元素节点,找不到返回null
    node.previousElementSibling
    	previousElementSibling返回当前元素上一个兄弟元素节点,找不到返回null
    注意: 这两个方法有兼容性问题,IE9以上才支持。
    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);
    
    // 兄弟节点解决兼容性问题(自己封装一个兼容性的函数)
    function getNextElementSibling(element) {
        var el = element;
        while (el = el.nextSibling) {
            if (el.nodeType === 1) {
                return el;
            }
        }
        return null;
    }

(2). 创建节点

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

(3). 添加节点

1. node.appendChild(child)
node.appendChild()方法将一个节点添加到指定父节点列表末尾。类似于CSS里面的after伪元素
2. node.insertBefore(child, 指定元素)
node.insertBefore() 方法将一个节点添加到父节点的指定子节点前面。类似于CSS里面的before伪元素
    // 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');
    ul.insertBefore(lili,ul.children[0]);
    // 4. 我们想要页面添加一个新的元素:1. 创建元素 2. 添加元素
留言框
    // 1. 获取元素
    var btn = document.querySelector('button');
    var text = document.querySelector('textarea');
    var ul = document.querySelector('ul');
    // 注册事件
    btn.onclick = function() {
        if (text.value == '') {
            alert('您没有输入内容');
            return falsel;
        }else {
            console.log(text.value);
            // (1) 创建元素
            var li = document.createElement('li');
            // 先有li,才能赋值
            li.innerHTML = text.value;
            // (2) 添加元素
            // ul.appendChild(li)
            ul.insertBefore(li, ul.children[0]);
        }
    }

(4). 删除节点

node.removeChild(child)
node.removeChild() 方法从DOM中删除一个子节点,返回删除的节点
    // 1. 获取元素
    var ul = document.querySelector('ul');
    var btn = document.querySelector('button');
    // 2. 删除元素 node.removeChild(child)
    // ul.removeChild(ul.children);
    // 3. 点击按钮以此删除里面的孩子
    btn.onclick = function() {
        if (ul.children.length == 0) {
            this.disabled = true;
        }else {
            ul.removeChild(ul.children[0]);
        }
    }
删除评论留言
    // 1. 获取元素
    var btn = document.querySelector('button');
    var text = document.querySelector('textarea');
    var ul = document.querySelector('ul');
    // 注册事件
    btn.onclick = function() {
        if (text.value == '') {
            alert('您没有输入内容');
            return falsel;
        }else {
            console.log(text.value);
            // (1) 创建元素
            var li = document.createElement('li');
            // 先有li,才能赋值
            li.innerHTML = text.value + "<a href='javascript:;'>删除</a>";
            // (2) 添加元素
            // ul.appendChild(li)
            ul.insertBefore(li, ul.children[0]);
            // (3) 删除元素,删除的是当前链接的li,他的父亲
            var as = document.querySelectorAll('a');
            for (var i = 0; i < as.length; i++) {
                as[i].onclick = function() {
                    // node.removeChild(child);  删除的是li,当前a所在的li,this.parentNode;
                    ul.removeChild(this.parentNode);
                }
            }
        }
    }

(5). 复制节点(克隆节点)

node.cloneNode()
node.cloneNode() 方法返回调用该方法的节点的一个副本。也称为克隆节点/拷贝节点、
注意:
	1. 如果括号参数为空或者false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的字节点
    2. 如果括号参数为true,则是深度拷贝,会复制节点本身以及里面所有的子节点
    var ul = document.querySelector('ul');
    // 1. node.cloneNode();  括号为空或者里面是false,浅拷贝,只复制标签不复制里面的内容
    // 2. node.cloneNode(true); 括号为true, 深拷贝,复制标签复制里面的内容
    var lili = ul.children[0].cloneNode(true);
    ul.appendChild(lili);

动态生成表格
    // 1. 先去准备好数据
    // var dates = [
    //     {
    //         name:'韩寒',
    //         subject:'javascript',
    //         score:98
    //     },{
    //         name:'猴子',
    //         subject:'javascript',
    //         score:99
    //     }
    // ]
    // 2. 往tbody里面创建行:有几个人(通过数组的长度)我们就创建几行
    var tbody = document.querySelector('tbody');
    for (var i = 0; i < datas.length; i++) { // 外面的for循环管行tr
        // 创建tr行
        var tr = document.createElement('tr');
        tbody.appendChild(tr);
        // 行里面创建单元格td 单元格的数量取决于每个对象里面的属性个数,for循环遍历对象,datas[i]
        for (var k in datas[i]) { // 里面的for循环管列 td
            // 创建单元格
            var td = document.createElement('id');
            // 把对象里面的属性值datas[i][k] 给td
            td.innerHTML = datas[i][k];
            tr.appendchild(td);

        }
    }
    // 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)
        }
    }

(6). 三种动态创建元素的区别

在这里插入图片描述

(7). DOM重点

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6. 事件高级

(1) 注册事件

1). 注册事件概述(绑定事件)

在这里插入图片描述

2). addEventListener事件监听方式
    EventTarget.addEventListener(type,listener[, useCapture])
    eventTarget.addEventListener() 方法将指定 监听器注册到eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。
    该方法接收三个参数:
    type: 事件类型字符串,比如click, mouseover, 注意这里不要带on
    listener: 事件处理函数,事件发生时,会调用该监听函数
    useCapture: 可选参数,是一个布尔值,默认值是false。学完DOM事件流后,我们再进一步学习
    var btns = document.querySelectorAll('button');
    // 1. 传统方式注册事件
    btns[0].onclick = function() {
        alert('hi');
    }
    btns[0].onclick = function() {
        alert('how are you!');
    }
    // 2. 事件监听注册事件,addEventListener
    // (1) 里面的事件类型是字符串,必定加引号,而且不带on
    // (2) 同一个元素,同一个事件可以添加多个监听器(事件处理程序)
    btns[1].addEventListener('click', function() {
        alert(33);
    })
    btns[1].addEventListener('click', function() {
        alert(22);
    })
    // 3. attachEvent ie9以前的版本支持
    btns[2].attachEvent('onclick', function() {
        alert(1);
    })
3).  attachEvent 事件监听方式
    eventTarget.attachEvent(eventNameWithOn, callback)
    eventTarget.attachEvent() 方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定的事件时,指定的回调函数就会被执行。
    eventNameWithOn: 事件类型字符串,比如 onclick, onmouseover ,这里要带on
    callback: 事件处理函数,当目标触发事件时回调函数被调用
    注意:IE8及早期版本支持
 4). 注册事件兼容性解决方案
    function addEventListener(element, eventName,fn) {
        // 判断当前浏览器是否支持 addEventListener 方法
        if (element.addEventListener) {
            element.addEventListener(eventName, fn); //第三个参数默认是false
        }else if (element.attachEvent) {
            element.attachEvent('on' + eventName, fn);
        }else {
            // 相当于element.onclick = fn;
            element['on' + eventName] = fn;
        }
    }
    // 兼容性处理的原则:首先照顾大多数浏览器,再处理特殊浏览器

(2) 删除事件

1. 删除事件的方式
    1). 传统注册方式
    	eventTarget.onclick = null;
    2). 方法监听注册方式
    	(1) eventTarget.removeEventListener(type, listener[, useCapture]);
    	(2) eventTarget.detachEvent(eventNameWithOn, callback);
    var divs = document.querySelectorAll('div');
    divs[0].onclick = function() {
        alert(11);
    // 1. 传统方式删除事件
        div[0].onclick = null;
    }
    // 2. removeEventListener 删除事件
    divs[1].addEventListener('click', fn) // 里面的fn不需要调用加小括号
    function fn() {
        alert(22);
        divs[1].removeEventListener('click', fn);
    }
    // 3.
    divs[2].attachEvent('onclick', fn1);
    function fn1() {
        alert(33);
        divs[2].detachEvent('onclick', fn1);
    }
2. 删除事件兼容性解决方案
    function removeEventListener(element, eventName, fn) {
        // 判断当前浏览器是否支持 removeEventListener 方法
        if (element.removeEventListener) {
            element.removeEventListener(eventName, fn); // 第三个参数,默认是false
        } else if (elsment.detachEvent) {
            element.detachEvent('on' + eventName, fn);
        } else {
            element['on' + eventName] = null;
        }
    }

(3) DOM事件流

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

    <div>
        <div class="son">son盒子</div>    
    </div>
    // 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');
    })

(4) 事件对象

1). 事件对象的兼容性方案
    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;
2). 事件对象的常见属性和方法

在这里插入图片描述

    // 常见事件对象的属性和方法
    // 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 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有个非常相似的属性 currentarget ie678不认识

    // 事件对象阻止默认行为
    // 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);
    }

(5) 阻止事件冒泡

1). 阻止事件冒泡的两种方式

在这里插入图片描述

    // 常见事件对象的属性和方法
    // 阻止冒泡,dom推荐的标准 stopPropagation()
    var son = document/querySelector('.son');
    son.addEventListener('click', function() {
        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');
    })
2). 阻止事件冒泡的兼容性解决方案
    if (e && e.stopPropagation) {
        e.stopPropagation();
    }else {
        window.event.cancelBubble = true;
    }

(6) 事件委托(代理,委派)

1. 事件委托
	事件委托也称为事件代理,在JQuery里面称为事件委派。
2. 事件委托的原理
	不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后再利用冒泡原理影响设置每个子节点。
以下案例:给ul注册点击事件,然后利用事件对象的target来找到当前点击的li,事件会冒泡到ul上,
ul有注册事件,就会触发事件监听器。
3. 事件委托的作用
	我们只操作了一次DOM, 提高了程序的性能
事件委托的核心原理:给父节点添加监听器,利用事件冒泡影响每一个子节点
    var ul = document.querySelector('ul');
    ul.addEventListener('click', function() {
        alert('知否知否,点击出弹框');
        // e.target 这个可以得到我们点击的对象
        e.target.style.backgroundColor = 'blue';
    })

(7) 常用的鼠标事件

1). 常用的鼠标事件

在这里插入图片描述
在这里插入图片描述

    // 1. contextmenu我们可以禁用右键菜单
    document.addEventListener('contextmenu', function(e) {
        e.preventDefault();
    })
    // 2. 禁止选中文字 selectstart
    document.addEventListener('selectstart', function(e) {
        e.preventDefault();
    })
2). 鼠标事件对象
    event对象代表事件的状态,跟事件相关的一系列信息的集合。
    现阶段我们主要是用鼠标事件对象: 
    MouseEvent 和键盘事件对象 KeyboardEvent。

在这里插入图片描述

    // 鼠标事件对象 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.screen);
        console.log(e.screenY);
    })
小天使

在这里插入图片描述
在这里插入图片描述

<style>
    img {
        position: absolute;
        top: 2px;
    }
</style>
<img src="1.jpg" 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';
    })

(8) 常用的键盘事件

1). 常用的键盘事件

在这里插入图片描述

    // 1. keyup 按键弹起的时候触发
    // document.onkeyup = function() {
    //     console.log('我弹起了');
    // }
    document.addEventListener('keyup', function(){
        console.log('我弹起了');
    })
    // 2. keydown按键按下的时候触发,能识别功能键,比如ctr1 shift左右箭头等
    document.addEventListener('keydown', function() {
        console.log('我按下了down');
    })
    // 3. keypress按键按下的时候触发,不能识别功能键,比如ctrl shift 左右箭头等
    document.addEventListener('keypress', function() {
        console.log('我按下了press');
    })
    // 4. 三个事件的执行顺序 keydown -- keypress -- keyup
2). 键盘事件对象

在这里插入图片描述

键盘事件对象中的keyCode属性可以得到相应键的ASCII码值
	1. 我们的keyup和keydown事件不区分字母大小写 a 和 A 得到的都是65
	2. 我们的keypress 事件区分字母大小写 a 97 和 A 得到的是65
    // 键盘事件对象中的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);
        // 我们可以利用keycode返回的ASCII码值来判断用户按下那个键
        if (e.keyCode === 65) {
            alert('您按下的a键');
        } else {
            alert('您没有按下a键')
        }
    })
    document.addEventListener('keypress', function(e) {
        console.log(e);
        console.log('press:' + e.keyCode);
    })
3). ASCII表

在这里插入图片描述

4). 模拟京东按键输入内容
    // 模拟京东按键输入内容
    // 核心思路:检测用户是否按下了s键,如果按下s键,就把光标定位到搜索框里面
    // 使用键盘事件对象里面的keyCode判断用户按下的是否是s键
    // 搜索框获得焦点:使用js里面的focus() 方法
    var search = document.querySelector('input');
    document.addEventListener('keyup', function(e) {
        // console.log(e.keyCode);
        if (e.keyCode === 83) {
            search.focus();
        }
    })
5). 模拟京东快递单号查询案例
    // 模拟京东快递单号查询案例
    // 快递单号输入内容时,上面的大号字体盒子(con)显示(这里面的字号更大)
    // 表单检测用户输入:给表单添加键盘事件
    // 同时把快递单号里面的值(value)获取过来赋值给con盒子(innerText)作为内容
    // 如果快递单号里面内容为空,则隐藏大号字体盒子(con)盒子
    var con = document.querySelector('.con');
    var jd_input = document.querySelector('.jd');
    jd_input.addEventListener('keyup', function() {
        console.log('输入内容啦');
        if (this.value == '' ) {
            con.style.display = 'none';
        } else {
            con.style.display = 'block';
            con.innerText = this.value;
        }
    })
    // 当我们失去焦点,就隐藏这个con盒子
    jd_input.addEventListener('blur', function() {
        con.style.display = 'nonde';
    })
    // 当我们获得焦点,就显示这个con盒子
    jd_input.addEventListener('focus', function() {
        if (this.value !== '') {
            con.style.display = 'block';
        }
    })
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值