05-DOM相关知识点讲解

DOM

DOM内容主要分为四部分:

  • 什么是DOM和节点;
  • 获取节点;
  • 节点操作(3种);
  • 属性操作(3种)。

什么是DOM和节点

  • DOM由节点组成;
  • DOM是树状模型;
  • DOM操作就是节点操作;
  • 每一个HTML标签都是一个元素节点
  • 标签中的文字就是文字节点
  • 标签的属性就是属性节点

获取节点:

直接获取:获取元素节点常用的方法主要有三种:通过id、标签名、类名:
  • 通过id获取:document.getElementById("box");
  • 返回一个标签,可以直接使用,获得属性值,设置属性。
  • 通过类名获取标签数组:document.getElementsByClassName("a");
  • 通过标签名获取标签数组:document.getElementsByTagName("div");
  • 获得的标签数组是一个伪数组
  • 通过标签名和类名获取到的标签数组,一般都是遍历之后再使用;特殊情况,数组中的值只有一个:
document.getElementsByTagName("div")[0];   //获取数组中的元素
document.getElementsByClassName("a")[0];   //获取数组中的元素
  • 通过名字获取(较少用):document.getElementsByName();
  • 通过tagNameNS获取(较少用):document.getElementsByTagNameNS();
<div id="box"></div>
<script>
    var div = document.getElementById("box");

    div.onclick = function () {
        alert(1);
    }
</script>
通过访问关系获取;
  • 有三种访问关系:父节点、兄弟节点和子节点;
  • 节点的访问关系是以属性形式存在的;
  • 父节点:调用者就是节点,一个节点只有一个父节点,调用方式:调用者.parentNode;
  • 兄弟节点:sibling
  • nextSibling:IE678中指下一个元素节点(标签);在火狐谷歌IE9+以后都是指下一个节点(包括空文档和换行节点);
  • nextElementSibling:在火狐谷歌IE9+都指的是下一个元素节点。
  • 总结:在IE678中用nextSibling,在火狐谷歌IE9+以后用nextElementSibling:下一个兄弟节点=节点.nextElementSibling || 节点.nextSibling;
  • 获取前一个兄弟节点:前一个兄弟节点=节点.previousElementSibling || 节点.previousSibling;
  • 单个子节点:
  • 第一个子节点=父节点.firstElementChild || 父节点.firstChild;
  • 最后一个子节点 = 父节点.lastElementChild || 父节点.lastChild;;
  • 所有子节点:
  • childNodes:它返回指定元素的子元素集合,包括HTML节点、所有属性、文本节点(W3C亲儿子,标准属性),子节点数组=父节点.childNodes; 获取所有节点
nodeType == 1,表示的是元素节点`记住`,元素就是标签
nodeTyoe == 2,表示的是属性节点,了解
nodeType == 3,表示的是文本节点,了解
  • children:非标准属性,它返回的是指定元素的子元素的集合,只返回HTML节点,甚至不返回文本节点,虽然不是标准的DOM属性,但是它和innerHTML方法一样,得到了几乎所有浏览器的支持。子节点数组=父节点.children; //用的最多,在IE678中,包含注释节点,所以在IE678中,不要将注释节点写在里面。

  • nodeType、nodeName、nodeValue(了解)

<div id="yijiang" class="jiangjiang" value="jiang">义江</div>
<script>
        var ele = document.getElementById("yijiang");
        var attr1 = ele.getAttributeNode("id");
        var attr2 = ele.getAttributeNode("value");
        var text = ele.firstChild;

        console.log(ele);       //<div id="yijiang" class="jiangjiang" value="jiang">义江</div>
        console.log(attr1);     //id="yijiang"
        console.log(attr2);     //value="jiang"
        console.log(text);      //"义江"

        console.log(ele.nodeType);      //1
        console.log(attr1.nodeType);    //2
        console.log(attr2.nodeType);    //2
        console.log(text.nodeType);     //3

        console.log(ele.nodeValue);      //null
        console.log(attr1.nodeValue);    //yijiang
        console.log(attr2.nodeValue);    //jiang
        console.log(text.nodeValue);     //义江
</script>
  • 补充:
  • 通过这两个属性parentNodechildren,可以获取到任意元素节点:节点.parentNode.children[index];:
function siblings(elm) {
        var a = [];
        var p = elm.parentNode.children;
        for(var i =0;i<p.length;i++) {
            if(p[i] !== elm) a.push(p[i]);
        }
        return a;
}

节点操作(3种)重要:节点的访问关系都是属性,而节点的操作都是函数或者方法。

  • 节点的创建:
    • 新的标签(节点)=document.createElement("标签名");
  • 添加(插入)节点:
    • 使用方法:父节点.appendChild(新节点);,父节点的最后插入一个新节点;
    • 使用方法:父节点.insertBefore(要插入的节点,参考节点);,在参考节点之前插入,如果参考节点为null,那么他将在节点最后插入一个节点。
  • 删除:
    • 使用方法:用父节点删除子节点父节点.removeChild(子节点):必须指定要删除的子节点
    • 使用方法:节点自己删除自己(自杀)node.parentNode.removeChild(node);,不知道父节点的情况下,可以这样使用。
  • 复制节点:
    • 新节点=要复制的节点.cloneNode(参数);,接受一个Boolean类型参数,true表示深复制(复制节点及其所有子节点),false表示浅复制(值复制节点本身,不复制子节点)。

属性操作(3种):

  • 获取:

    • 节点.属性或者节点[属性]
    • 节点.getAttribute("属性")
  • 设置:节点.setAttribute(属性,值)

  • 删除:节点.removeAttribute(属性);

  • 注:

    • IE6、7不支持;
    • 元素节点.属性(元素节点[属性]):资料上说该方法绑定的属性值不会出现在标签上,但是经测试通过这种方法绑定的属性如果是标签原本就有的也会出现在标签上,如果是用户自定义的属性就不会出现在标签上;
    • get/set/removeAttribute:绑定的属性值会出现在标签上,推荐使用;
    • 两种方式不能相互访问:赋值和获取值必须使用同一种方法。
  • 练习:

    • 切换图片(a连接+图片);
      • 如果<a href="www.baidu.com">跳转</a>,点击a,页面会进行相应跳转,在onclick绑定的函数最后加return false;或者如果是行内绑定就在onclick最后加return false;就可阻止相应的跳转。
    • 显示和隐藏盒子;
      • 显示隐藏盒子的同时修改按钮的文字,使用innerHTML进行按钮文字的修改。
    • 美女相册
//2.绑定事件(利用for循环绑定事件)
for(var aIndex in aArr){
        aArr[aIndex].onclick = function () {
            show.src = this.href;
    //warning       des.innerHTML = aArr[aIndex].title;
            des.innerHTML = this.title;
            return false;
        }
}
- 注:绑定描述时,只能通过this获取title,不能通过aArr[aIndex]获取,因为绑定事件时候,并没有立刻执行事件,当用户点击时已经无法通过Arr[aIndex]获取对应标签。

排它思想

  • 通常和for循环连用,先干掉所有人,然后再单独处理某一个特殊人。
  • 练习:
    • tab切换;

绑定事件:三种方法

  • 通过匿名函数绑定;
  • 通过函数名绑定(不能加小括号,否则就是绑定返回值了);
  • 行内绑定:<div class="content" onclick="fn()">,一定要加小括号,否则就是字符串了。(经测试发现,行内绑定的方法不能写在window.onload里面,元素加载时找不到方法)

onload事件

  • 页面加载完毕(包括文本和图像)时候调用这个事件:window.onload

  • 主要用途:

    • js的加载是和html的加载同步进行的。如果使用元素在定义元素之前,容易报错;
    • 整个页面上的所有元素加载完毕时再执行js内容;
    • window.onload:可以预防使用标签在定义标签之前。
  • 补充:

    • value:标签的value属性;
    • innerHTML:获取双闭合标签里面的内容。(识别标签)
    • innerText:获取双闭合标签里面的内容。(不识别标签)
    • 老版本的火狐不支持innerText,支持textContent。

DOM对象的属性

  • 表单元素的属性

    • type
    • value
    • checked
    • selected
    • disabled
  • DOM对象的属性练习:

    • 显示隐藏二维码;
      • 可以替换字符串(了解):div.class.replace("old","new");;
erweima_s.onmouseover = function () {
        erweima_b.className = "erweima-big show";
    };
erweima_s.onmouseout = function () {
        erweima_b.className = erweima_b.className.replace("show","hide");
    };
  • 点击按钮禁用/解禁文本框;
    • inp.removeAttribute("disabled");
<body>
    <hr>禁用/解禁文本框 <br>
    账  号:<input value="yijiangwnag" class="account"><button>禁用</button><button>解禁</button>
    <script>
        window.onload = function () {
            var account = document.getElementsByClassName("account")[0];
            var ban = document.getElementsByTagName("button")[0];
            var banCancel = document.getElementsByTagName("button")[1];
            ban.onclick = function () {
//                account.setAttribute("disabled",true);
                account["disabled"] = true;
            };
            banCancel.onclick = function () {
//                account.removeAttribute("disabled");
                account["disabled"] = false;
            };
        }
    </script>
</body>
  • 输入事件与事件焦点onfocus【淘宝、京东输入框】(获取焦点:onfocus,失去焦点:onblur);
    • 京东的input输入框获取到焦点时删除内容,失去焦点时显示内容;
    • 淘宝的input输入框在获取到焦点时没有变化,输入内容之后文字消失,当删除内容之后文字恢复出现:oninput事件:删除/输入内容时候调用进入页面时候直接获取光标焦点:inp.focus();
<body>
        京东:<input id="jd" value="我是京东"><br>
        淘宝:<input id="tb"><label class="tbLabel">我是淘宝</label><br>
        placeholder:<input placeholder="我是placeholder">
    <script>
        //京东/淘宝输入框
        var jd = document.getElementById("jd");
        var tb = document.getElementById("tb");
        var tbL = document.getElementsByClassName("tbLabel")[0];
        jd.onfocus = function () {
            if (jd.value == "我是京东"){
                jd.value = "";
            }
        };
        jd.onblur = function () {
            if (jd.value == ""){
                jd.value = "我是京东";
            }
        };
        tb.oninput = function () {
            if (tb.value == ""){    //但是淘宝连续输空格label不消失的bug日后解决
                tbL.className = "tbLabel show";
            }else {
                tbL.className = "tbLabel hide";
            }
        };
    </script>
</body>
  • 检测用户名、密码是否是6~12位,如果不满足要求高亮显示文本框;
    • html中的input标签行内调用function的时候,是通过window去调用function的;
    • 标签之后在函数参数里传递的this才是指的标签本身。只做了解,平时使用时尽量不要在行内式中调用函数;
    • html中的input标签行内调用function的时候,function定义不能写在window.onload里面,标签加载时会找不到。
<body>
    账号:<input id="checkAcc" onblur="fn(this)"> <br>
    密码:<input id="checkSec" onblur="fn(this)">
    <script>
    //要求用户名3~6位,密码在6~8位,如果不正确就高亮显示(显示红色)
    function fn(aaa) {
        console.log(this);
        if (aaa.value.length > 12 || aaa.value.length < 6){
            aaa.className = "wrong";
        }else {
            aaa.className = "right";
        }
    }
    </script>
</body>
  • 设置下拉框中的选中项(水果名称);
    • 点击按钮,把下拉框中的鳄鱼对应的选择属性设置selected,直接添加selected属性即可,或者个selected属性赋任何值都可以;
    • 补充:如果打印sel.value,就会打印被选中项的索引;
    • 如果要去掉选中,可以将对应的selected属性值设为false,但是有些浏览器不支持,最好是remove该属性。
    <body>
    <button id="selectFish">水产品</button><button id="rid">去除</button>
    <br>
    <select>
        <option id="banana">香蕉</option>
        <option>茄子</option>
        <option id="fish" >鳄鱼</option>
        <option>西瓜</option>
    </select>
    <script>
        //挑选出下拉列表中的某一项
        var selBtn = document.getElementById("selectFish");
        var ridBtn = document.getElementById("rid");
        var eyu = document.getElementById("fish");
        var banana = document.getElementById("banana");
        selBtn.onclick = function () {
            eyu.selected = true;
        };
        ridBtn.onclick = function () {
            eyu.selected = false;
            banana.selected = true;
        };
    </script>
    </body>
  • 给文本框赋值,获取文本框的值;
<body>
    <input type="text"> <br>
    <input type="text"> <br>
    <input type="text"> <br>
    <input type="text"> <br>
    <input type="text"> <br>
    <button>赋值</button>
    <button>取值</button>
<script>
    var inpArr = document.getElementsByTagName("input");
    var btnArr = document.getElementsByTagName("button");
    //赋值
    btnArr[0].onclick = function () {
        for(var i=0; i<inpArr.length; i++){
            inpArr[i].value = i;
        }
    };
    //取值
    btnArr[1].onclick = function () {
        var valueArr = [];
        for(var i=0; i<inpArr.length; i++){
            valueArr.push(inpArr[i].value);
        }
        console.log(valueArr.join(" "));
    };
</script>
</body>
  • 全选反选;
  • 隔行变色(使用childNodes实现)。

DOM的样式设置(两种方式)

className
style
  • 获取样式

    • DOM的style属性只能获取标签中使用style设置的样式,无法获取嵌入或外部样式;
    • style.cssText获取style里面的字符串;
  • 设置样式

    • 无论设置还是获取只能操作行内式。
  • style属性设置和获取(style是一个对象,不能获取内嵌和外链)

    • 样式少的时候使用;
    • style是对象;
    • 值是字符串,没有设置时是"";
    • 命名规则,驼峰命名,和css不一样;
    • 设置了类样式不能获取(只和行内式交互,和内嵌式和外链无关);
    • box.style.cssText = "字符串形式的样式"。
  • style常用属性

    • backgroundColor;
    • backgroundImage;
    • color;
    • width;
    • height;
    • border;
    • opacity(IE8以前filter:alpha(opacity=xx));
    • 注意DOM对象style属性和标签中style内的值不一样,因为在JS中-不能作为标识符;
      • backgroundColor -> DOM中;
      • background-color -> CSS中。
  • 位置:

    • position;
    • left;
    • top;
    • right;
    • bottom;
    • z-index。
  • 练习:

    • 给变div的大小和透明度;
    • 当前输入的文本框高亮显示;
    • 高级隔行变色、高亮显示;
    • 百度皮肤;
      • 获取body:
var body = document.getElementsByTagName("body");
//或者
var body = document.body;   //document内置了直接获取body的方法
  • 显示隐藏/关闭广告/显示二维码(隐藏方法);
    • display(用的较多,可以占位置):元素隐藏之后,不占位置,页面上的元素会重新排列;
    • visibility:元素隐藏之后占位置(hidden、visible);
    • opacity(用的较多,控制器来方便);
    • position。
  • 提高层级。

封装

  • 练习
    • 菜单练习

动态创建元素(操作元素)三种方式

  • 方式一:document.wtrite(),document.write()能够识别标签;,不常用,因为容易覆盖之前的标签;

  • 方式二:innerHTML,直接写会覆盖之前的,一般这样使用div.innerHTML += "<li>xxx</li>;",用的比较多,绑定属性和内容比较方便;

  • 方式三:利用DOM的API创建,document.createElement("li"),用的也比较多,指定数量的时候一般用这种方法。

  • 操作元素:

    • 父元素.appendChild(子元素);:在父元素的最后面添加子元素;
    • 父元素.insertBefore(newEle,aaa);:在指定位置添加;
    • 父元素.removeChild(子元素);
    • 父元素.replaceChild(newEle,oldEle);,用的较少;
    • 需要克隆的节点.cloneNode(true);,参数为true时,是深拷贝,一般都是用深拷贝。
  • 练习:

    • 动态创建列表,高亮显示(四大美女);
    • 祝愿墙;
    • 左右切换城市或者水果;
      • div.onclick = function(){//code};,如果函数不带参数,我们可以直接绑定一个函数名;但是如果函数带参数,我们需要在匿名函数中去调用这个带参数的函数。
    • 动态创建祝愿墙;
    • 在线会员列表;
    • 模拟百度搜索文本框;
      • a.indexOf(b);返回b在a中的位置,如果`b="ccc;",那么返回a中ccc的第一个c的位置,如果a中没有ccc,那么就返回-1;

动态创建表格(了解)

  • 方式一:createElement();
  • 方式二:
  • rows (只读,table和textarea能用);
  • insertRow() (只有table能用);指定索引值之前插入
  • deleteRow() (只有table能用);
  • cells (只读,table和textarea能用);
  • insertCell() (只有tr能调用)
  • deleteCell() (只有tr能调用)

内置对象

  • 内置对象就是指这个语言自带的一些对象,供开发者使用,这些对象提供了一些常用的或者最基本而又必要的功能。
对象名称 对象说明
Arguments 函数实参集合
Array 数组
Boolean 布尔对象
Date 日期时间对象
Error 异常对象
Function 函数构造器
Math 数学对象
Number 数值对象
Object 基础对象
RegExp 正则表达式对象
String 字符串对象
Date
  • 日期对象四种声明/定义方式

    • 直接定义:var date1 = new Date();获取当前时间;
    • 设定指定时间(兼容最强):var date2 = new Date("2017/1/1 20:12:12");
    • 不常用:var date3 = new Date("Wed Jan 27 2016 12:00:00 GMT+0800(中国标准时间)");
    • var date4 = new Date(2016,1,27);
    • 后两种兼容性不好,不建议使用。
  • Date对象的方法:

    • getDate() //获取日:1-31;
    • getDay() //获取星期:0-6(0代表周日)
    • getMonth() //获取月:0-11(1月从0开始)
    • getFullYear() //获取完整年份(浏览器都支持)
    • getHours() //获取小时:0-23
    • getMinutes() //获取分钟:0-59
    • getSeconds() //获取秒:0-59
    • getMilliseconds() //获取毫秒
    • getTime() //返回累计毫秒数(从1970/1/1午夜)
  • 返回距离1970/1/1毫秒数

    • var date = Date.now();
    • var date = +new Date();
    • var date = new Date().getTime();
    • var date = new Date().valueOf();
    • 返回1970/1/1午夜与当前日期和时间之间的毫秒数。
  • 案例:

    • 日历:显示当前年月日和星期
    • 倒计时:苹果发布会:倒计时包括天时分秒;
      • 当任一阶段的时间小于10时,要在前面补0,否则会有闪动;
      • 解决方案:hour = hour<10?"0"+hour:hour;
String(Boolean/Number)
  • 给索引查字符(charAt/charCodeAt)
    1. charAt,获取相应位置字符(参数:字符位置)
      • 字符串中第一个字符的下标是0。如果参数index不在0与string.length之间,该方法将返回一个空字符串;
    2. charCodeAt,获取相应位置字符编码(参数:字符位置)
      • charAt()方法和charCodeAt()方法用于选取字符串中某一位置上的单个字符;
      • 区别:charCodeAt()方法,它并不返回指定位置上的字符本身,而是返回该字符在Unicode字符集中的编码值。如果该位置没有字符,返回值为NaN。
字符/字符编码 = Str.charAt/charCodeAt(索引值);
  • 简单数据类型也有属性,因为底层会进行数据类型转换,但是简单数据类型``不能绑定``属性和方法

  • 给字符查索引(indexOf/lastIndexOf)

    • indexOf,从前向后索引字符串的位置(参数:索引字符串);
      • 从前向后寻找并返回第一个符合元素的位置。
    • lastIndexOf,从后向前索引字符串的位置(参数:索引字符串);
      • 从后向前寻找并返回第一个找到的符合元素的位置。
    • 练习:求一个字符串占多少字符位。(一个汉字占两个字符位,英文的所有字符在0-127之间)。长度只看字符个数,不分中英文。
  • url编码和解码(了解)

    • uri(uniform resource identifiers),通过资源标识符进行编码,以便发送给浏览器。有效的uri中不能包含某些字符,例如空格。而这uri编码方法就可以对uri编码,它们用特殊的utf-8编码替换所有无效的字符,从而让浏览器能够接受和理解;
    • encodeURIComponent()函数可以把字符串作为URI组件进行编码;
    • decodeURIComponent()函数可以把字符串作为URI组件进行解码。
  • 字符串的连接:

新字符串 = str1.concat(str2);
  • 字符串的截取
    • slice(参数1,参数2);,截取字符串,参数1代表截取的起始位置,参数2代表终点位置,两个参数都是索引值。

      • (2,5):正常包左不包右;
      • (2):从指定的索引位置截取到最后
      • (-3):从倒数第几个截到最后;
      • (5,2):前面的数大于后面的数,返回空。
    • substr(参数1,参数2),截取字符串,参数1是截取起始位置,参数2是截取的长度,参数1是索引值,参数2是数值。

      • (2,4):从索引值为2的位置开始,截取4个字符;
      • (1):一个值,从指定位置截取到最后;
      • (-3):从倒数第几个截取到最后;
      • 不包括前大后小的情况。
    • substring(参数1,参数2)同slice

      • 不同点:参数能智能调换位置;
      • 参数为负值时,将获取全部字符串。
      • (2,5),正常包左不包右;
      • (2),从指定的索引位置截到最后;
      • (-3),截取全部字符;
      • (5,2),前面大后面小会智能调换位置(2,5);
      • 两个参数都是索引。
  • 特殊方法简介

    • trim() //只能去除字符串前后的空格,中间的去不了;
    • replace(参数1,参数2) //替换,将字符串中的参数1(假定为"aaa")替换成参数2,从前往后查找"aaa",只能替换一次;如果要全部替换就将"aaa"改为/aaa/g;现在只能替换全部是小写的"aaa",如果要不区分大小写,就写成/aaa/gistr.replace(/aaa/gi,"bbb");
    • split("&") //字符串变数组:如果没有参数,将把整个字符串作为一个元素添加到数组中;如果参数是空字符串"",将会把字符串的每一个字符当成一个元素添加到数组中;如果参数是指定分隔符"&",将会把字符串用&分割成元素然后分别添加到数组中。
    • 大小写转换:
      • to(Locale)UpperCase() //全部转换成大写;
      • to(Locale)LowerCase() //全部转换成小写。
  • 基本包装类型:

    • 为了方便操作基本数据类型,JavaScript还提供了三个特殊的引用类型:String/Number/Boolean;
    • 例如:
var s1 = "zhangsan";
var s2 = s1.substring(5);
  • 解析:s1是基本数据类型,基本数据类型是没有属性和方法的;当调用s1.substring(5)时,先把s1包装成String类型的临时对象,再调用substring方法,最后销毁临时对象;实现过程如下:
var s1 = "zhangsan";
//当调用s1.substring(5)时,具体过程解析如下:
var s1Temp = new String(s1);
var s2 = s1Ttemp.substring(5);
s1Temp = null;
  • 字符串练习

    • 截取字符串“我爱你中国,我亲爱的母亲”中的“中国,我亲爱”;
    • "abcoefoxyozzopp"查找字符串中所有"o"出现的位置;
    • 把字符串中所有的"o"替换成"!";
    • 判断一个字符串中出现次数最多的字符,统计这个次数。
    • 给定一个字符串:"abaasdffggghhjjkkgfddsssss3444343"问题如下:
      • 字符串的长度;
      • 取出指定位置的字符,如:0、3、5、9等;
      • 查找指定字符是否在以上字符串中存在,如i、c、b等;
      • 替换指定的字符,如g换成22,ss替换成b等操作方法;
      • 截取指定开始位置到结束位置的字符串,如取得1-5的字符串;
      • 找出以上字符串中出现次数最多的字符和出现的次数。
  • 获取节点元素的封装(重点

HTML方法(了解)
  • anchor(); //创建a链接
  • big();
  • sub();
  • sup();
  • link();
  • bold();
  • str.link(); //返回值是字符串
Math
  • Math.abs();:取绝对值;
  • Math.floor();:向下取整;
  • Math.ceil();:向上取整;
  • Math.round();:四舍五入取整;
  • Math.random();:获得0~1之间的随机数。
addEventListenner(事件监听器,原事件被执行的时候,后面绑定的事件照样会被执行,不会发生层叠现象,更适合团队开发。如果同一个按钮绑定多个onclick事件,后面的会层叠前面的,只会执行最后一个onclick绑定事件。)
  • 使用方法
    • btn.addEventListener("click",fn);;
    • 调用者是事件源,参数1是事件名(不带on不带小括号),参数2是执行的函数,参数3是捕获或者冒泡(以后再讲)。
  • 实现原理(事件监听原理)(了解,自己封装一个)
    • 不能直接执行函数,要先进行判断;
    • 如果以前绑定过事件,那么把以前的事件执行完毕再执行现在的函数;
    • 如果没有被定义过事件,该事件源的该事件对应的属性应该是null,对应的Boolean值应该为false;如果已经定义过该事件源的该事件,该事件源的该事件属性应该是function本身,对应的Boolean值类型为true;
    • 可以通过绑定属性的方式绑定方法可以通过获取属性的方式来获取方法
<body>
    <button>按钮一</button>
    <button>按钮二</button>

    <script>
        var btn1 = document.getElementsByTagName("button")[0];
        var btn2 = document.getElementsByTagName("button")[1];

        btn1.onclick = function () {
            console.log("我是王老大");
        };

        fn("click",fn1,btn1);
        fn("click",fn2,btn1);
        fn("click",fn3,btn1);
        fn("mouseover",fn2,btn2);

        function fn1() {
            console.log("黄河入海流;关公耍大刀");
        }
        function fn2() {
            console.log("我自横刀向天笑,去留肝胆两昆仑");
        }
        function fn3() {
            console.log("床前明月光,一片白茫茫");
        }

        function fn(str, func, ele) {
            var oldFunc = ele["on"+str];
            ele["on"+str] = function () {
                if (oldFunc){
                    oldFunc();
                }
                func();
            }
        }
    </script>
</body>
  • 兼容性(addEventListener和attachEvent)
    • 事件名称的区别:
      • addEventListener中第一个参数type是click、load,不带on;ele.addEventListener("click",fn);
var btn3 = document.getElementsByTagName("button")[2];
btn3.addEventListener("click",fn33);
function fn33() {
        console.log("你点了addEventListener");
}
  • attachEvent中第一个参数type是onclick、onload。ele.attachEvent("onclick",fn);
var btn4 = document.getElementsByTagName("button")[3];
btn4.attachEvent("onmouseover",fn44);
function fn44() {
        console.log("你碰到attachEvent了");
}
  • this的区别:
    • addEventListener:事件处理程序会在当前对象的作用于运行,因此,事件处理程序的this就是当前对象;
    • attachEvent:事件处理程序是在全局作用域下运行,因此this就是window。
  • 兼容性:
    • addEventListener支持火狐、谷歌、IE9+;
    • attachEvent兼容IE678。
  • 解决方案:
    • 通过判断调用的方式来兼容IE678;
    • 判断浏览器是否支持该方法,如果支持就直接调用,如果不支持就用其它方法。
//兼容性写法,定义一个对象EventListen
        EventListen = {
            addEvent: function (ele,fn,str) {
                if (ele.addEventListener){
                    ele.addEventListener(str,fn);
                }else if (ele.attachEvent){
                    ele.attachEvent("on"+str,fn);
                }else{
                    ele["on"+str] = function () {
                        console.log("都不能绑定");
                    }
                }
            }
        };

        EventListen.addEvent(btn4,fn44,"mouseover");
  • 移除事件(解决绑定)
    • btn.onclick = null;
    • 谷歌、火狐、IE9+:btn.removeEventListener("click",fn),只能移除通过addEventListener方法添加的事件;
    • IE678:btn.detachEvent("onclick",fn),只能解绑通过attachEvent方法绑定的事件;
EventListen = {
        deleteEvent:function (ele,fn,str) {
            if (ele.removeEventListener){
                ele.removeEventListener(str, fn);
            }else if (ele.detachEvent){
                ele.detach("on"+str,fn);
            }else {
                ele["on"+str] = null;
            }
        }
};
EventListen.deleteEvent(btn4,fn,"click");
  • 封装
//封装
EventListen = {
    addEvent: function (ele,fn,str) {
        if (ele.addEventListener){
            ele.addEventListener(str,fn);
        }else if (ele.attachEvent){
            ele.attachEvent("on"+str,fn);
        }else{
            ele["on"+str] = function () {
                console.log("都不能绑定");
            }
        }
    },

    deleteEvent:function (ele,fn,str) {
        if (ele.removeEventListener){
            ele.removeEventListener(str, fn);
        }else if (ele.detachEvent){
            ele.detach("on"+str,fn);
        }else {
            ele["on"+str] = null;
        }
    }
};
var btn = document.getElementsByTagName("button")[4];
EventListen.addEvent(btn,fn1,"click");
EventListen.deleteEvent(btn,fn1,"click");

事件(DOM重点

什么是事件
  • JavaScript是事件驱动的;
  • 什么是事件
    • 触发-响应;
    • 事件的概念:
      • 事件源:触发事件的对象;
      • 事件名称:click、mouseover等;
      • 事件处理程序:onclick、onmouseover等。
注册事件的两种方式
  • onclick:

    • DOM0;
    • 几乎所有的浏览器都支持;
  • addEventListener

    • DOM2;
    • 现代浏览器支持,IE9+;
    • 可以给同一个事件注册多个事件处理程序;
    • 可以选择捕获或者冒泡;
    • IE9以前使用atachEvent。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 一、JS前言 (1)认识JS 也许你已经了解HTML标记(也称为结构),知道了CSS样式(也称为表示),会使用HT...
    凛0_0阅读 2,721评论 0 8
  • 第1章 认识JS JavaScript能做什么?1.增强页面动态效果(如:下拉菜单、图片轮播、信息滚动等)2.实现...
    mo默22阅读 1,171评论 0 5
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,503评论 6 13
  • 《ijs》速成开发手册3.0 官方用户交流:iApp开发交流(1) 239547050iApp开发交流(2) 10...
    叶染柒丶阅读 4,734评论 0 7
  • 时间: 17:10地点: 学校门口绿化带一角任务: 接老弟放学 16:30,老妈和表姐在附近买菜,我就光荣的被派来...
    转不出的时光阅读 187评论 0 0