w简书的markdown不支持[toc]? 😭
不知不觉,从开始做android的项目后就很少写JS了,最近项目中需要用到大量的H5,也来凑凑HTML5开发的热闹。。。当然前提要学好JS,好记性不如烂笔头,开始学着写点笔记,提升学习效率~
这里只是记录一些比较容易忘记,API之类的需要时再去查阅
[toc]
事件对象
接受对象的差异性
W3C可直接通过参数接收事件对象,而IDE自己定义了一个Event对象,通过window.event
获取。
兼容获取事件对象的代码
<input type="button" id="btn" value="提交"/>
<script>
var btn = document.getElementById("btn");
btn.onclick = function(event){
var e = event || widnow.event;
alert(e);
}
</script>
鼠标事件
鼠标事件的兼容性问题
onmousemove:鼠标移动
onmousedown:鼠标点击
onmouseup:鼠标松开
onmouseover:鼠标移动到元素区域内
onmouseout :鼠标移出元素
在这三个事件对象中,有一个button属性,表示按下或者释放的按钮,遗忘的是对于这个button属性,坑爹的IE也与W3C不同(怪不得你爹不要你了)
W3C中的button属性
IE中的button属性
可以看出,IE和W3C在button属性上各个数值所表示的按钮和状态都不一样,但是一般我们只需要兼容W3C那三种就好了
兼容代码
function getButton(evt) {
var e = evt || window.event;
if (evt) {
return e.button;
} else
if (window.event) {
switch(e.button) {
case 1 :
return 0;
case 4 :
return 1;
case 2 :
return 2;
}
}
}
document.onmouseup = function (evt) {
if (getButton(evt) == 0) {
alert('按下了左键!');
} else if (getButton(evt) == 1) {
alert('按下了中键!');
} else if (getButton(evt) == 2) {
alert('按下了右键!' ); }
};
鼠标事件-可视区和坐标的获取
可通过clienX,screex获取,这个就不记录了,查一下文档即可
键盘事件
onkeydown
onkeypress:只对能在屏幕上输出字符的按钮有效果
onkeyup
属性:
keyCode:键码---获取一个代码,与键盘特定的键对应,与ASCII码中对应的编码相同(不区分大小写)
charCode:字符编码 --- 只有在keypress中才包含值,对应的是键所代码的字符的ASCII编码(区分大小写)
document.onkeypress = function (event) {
alert("charCode == "+ event.charCode); //得到相应的 charCode
};
document.onkeydown = function (event) {
alert("keyCode == "+ event.keyCode); //得到相应的 keyCode
};
兼容性问题:
不同浏览器中,获取的keyCode(键码)和charCode(字符编码)有可能不一样,要谨慎操作
事件对象的其他属性
事件冒泡
事件流:当几个具有事件的元素叠在一起的时候,那么你点击一个元素后,所有层叠在你点击范围内的元素都会触发事件。
来个简单的图感受一下。
Button,紫色和蓝色的DIV都具有点击事件,因为Button在最内层,当点击button时,click事件会从内往外触发----这就是事件冒泡(特征:从里往外触发)
事件捕获:与事件冒泡相反,是从外往内触发
阻止冒泡
从前面的==事件的其他属性==中看到,关于阻止事件冒泡IE和W3C有不同的属性
IE:是通过cancelBubble = true 取消事件冒泡
W3C:调用stopProgagation()方法取消事件冒泡
阻止的兼容方法
function stopPro(event) {
var e = event || window.event;
window.event ? e.cancelBubble = true : e.stopPropagation(); }
事件的绑定
事件的绑定有两种方式
一,传统的事件绑定,分为内联模型,脚本模型
二,DOM2级的现代事件绑定
传统的事件绑定
内联模型
基本上很少用,维护起来简直想杀人。。。
下面这两种形式
<input value="点击" id="btn" type="button" onclick="alert('aaa')">
<input value="点击" id="btn" type="button" onclick="btnOnclick()">
脚本模型
即用JavaScript获取DOM设置事件
传统事件绑定的问题
一、多次绑定会被覆盖
很直观的问题,重复绑定会覆盖掉前面的
/*缺点1:绑定多次会被覆盖 */
window.onload = function(){
alert("onload 111111");
}
window.onload = function(){
alert("onload 2222222");
}
二、this的指向问题
var myDiv = document.getElementById("myDiv");
myDiv.onclick = toBlue;
function toBlue(){
alert(this);//第一次就是DivElement 第二次就是window了
this.className = "blue";
this.onclick = toRed;
}
function toRed(){
this.className = "red";
this.onclick = function(){
toBlue();
}
}
三、too much recursion的问题
当你不停的add事件时,可能会报出too much recursion的错误,这是因为你积累了太多的保存事件,太多递归导致浏览器卡死。
解决方法:用完的事件,立即处理掉
var myDiv = document.getElementById("myDiv");
//可以通过[]的形式获取绑定事件
myDiv['onclick'] = function(){
alert("aaa");
};
/**
* obj : 要移出的元素
* type: 要移出的事件类型 click等
**/
function removeEvent(obj,type){
if(obj['on'+type]) obj['on'+type] = null;
}
W3C事件处理
DOM2级中,定义了addEventListener和removeEventListener方法。最后一个参数 true:表示捕获,false:表示冒泡
一,解决了this的指向问题,再也不怕too much recursion了
我们将上面this指向的代码稍微修改一下
var myDiv = document.getElementById("myDiv");
myDiv.addEventListener('click',toBlue);
function toBlue(){
alert(this);//都是DivElement
this.className = "blue";
this.addEventListener('click',toRed);
}
function toRed(){
this.className = "red";
myDiv.addEventListener('click',function(){
toBlue();
});
}
二,解决重复绑定覆盖的问题
var myDiv = document.getElementById("myDiv");
myDiv.addEventListener('click',function(){
alert("event 11111");
})
/**
* 不再覆盖,两个都会执行,共存
* */
myDiv.addEventListener('click',function(){
alert("event 222222");
})
IE的事件处理函数
IE9就全面支持W3C的事件函数了,这里就做个简单的了解
提供了两个方法:
attachEvent()
detachEvent()
几个不同点
1,IE不支持捕获,只支持冒泡
2,IE不能屏蔽重复的函数
3,IE中this指向的是window对象
4,之前说到,IE在传统事件中接收不到event事件对象的
但是attchEvent可以做到。。。真是让人爪机
不想装个IE浏览器,这就不测试了,做个简单的记录,方便以后用到的时候查询
添加/删除事件,得到事件对象的兼容代码
//添加事件兼容
function addEvent(obj, type, fn) {
if (obj.addEventListener) {
obj.addEventListener(type, fn);
} else
if (obj.attachEvent) {
obj.attachEvent('on' + type, fn); }
}
//移除事件兼容
function removeEvent(obj, type, fn) {
if (obj.removeEventListener) {
obj.removeEventListener(type, fn);
} else if (obj.detachEvent) {
obj.detachEvent('on' + type, fn);
}
}
//得到事件目标
function getTarget(evt) { if (evt.target) {
return evt.target;
} else if (window.event.srcElement) {
return window.event.srcElement; }
}
事件其他补充(主要是兼容方面)
获取移入和移出的DOM对象的兼容问题
W3C版:事件对象属性:relatedTarget
IE版:fromElement 和 toElement,分别对应 mouseover 和 mouseout。
不同的实现,又需要兼容的代码~
function getTarget(evt) {
var e = evt || window.event;
if (e.srcElement) {//如果支持,就是IE浏览器(srcElement:事件目标)
if (e.type == 'mouseover') {
return e.fromElement;
} else if (e.type == 'mouseout') {
return e.toElement;}
} else if (e.relatedTarget) {
//如果支持 relatedTarget,表示 W3C ;
return e.relatedTarget;
}
}
取消事件默认行为的兼容性问题
场景:取消超链接的默认行为.
解决方法一:
设置 return false。
缺点:
1)、必须写在最后,那么中间的代码执行后,
可能执行不到return false;(例如中间报错了,但是页面依旧会跳转)
2)、如果写在最前面,那么就无法做一些跳转判断了(通过一段逻辑判断后才决定是否跳转)
` <a id="aLink" href="http://baidu.com">aaaa</a>`
var aLink = document.getElementById("aLink");
aLink.onclick = function(){
/**
*
* */
var person = function(){
}
var p = new Person();
p.show();//这里没有show方法,报错了,所以后面的return false没有执行到,页面依旧跳转了
return false;
}
解决方法二:取消事件的默认行为
W3C:event.preventDefault(); IE:
window.event.returnValue = false;
头疼,又需要兼容。。。
兼容代码
function preDef(event) {
var e = event || window.event;
if(e.preventDefault) {
e.preventDefault();
}else {
e.returnValue= false;
}
}
oncontextmenu事件
可用于取消右键事件,提升浏览器性能
window.document.oncontextmenu = function(event){
var e = event || window.event;
if(e.preventDefault) {
e.preventDefault();
}else {
e.returnValue= false;
}
}