一、事件
    1、事件绑定:
         1. elem.onxxx = function(){},this指向elem,只能绑定一个处理函数,基本等同于写在HTML行间(句柄写法)
         2. elem.addEventListener('事件类型',处理函数,false),this指向elem,可绑定多个处理函数
         3. elem.attachEvent('on'+事件类型, 处理函数),this指向window。(解决方案:外部单独写处理函数,里面的函数体调用真正的处理函数,call的方式),可绑定多个处理函数,而且同一个函数绑定多次可以多次执行。
         经典鄙视题:给li列表循环绑定click事件,输出他们的索引。

        var oLi = document.getElementsByTagName('li');
        for(var i = 0; i < oLi.length; i++){
            (function(j){
                oLi[i].onclick = function(){
                console.log(j);
                }
            }(i))
        }

    2、解除事件:
         1. elem.onxxx = null/false,给赋一个空值就完事儿
         2. elem.removeEventListener('事件类型',同一个函数引用,false),绑定匿名函数,无法解除
         3. elem.detachEvent('on'+事件类型, 同一个函数引用)

         封装绑定事件函数,兼容所有浏览器

        function addEvent(elem, type, handle){
	        if(elem.addEventListener){
	        	elem.addEventListener(type, handle, false);
        	}else if(elem.attachEvent){
        		elem.attachEvent('on' + type, function(){
        			handle.call(elem);//解决this指向的问题
        		})
        	}else{
        		elem['on' + type] = handle;
          	}
        }

二、事件处理模型:冒泡、捕获(触发顺序为:首先捕获,然后源元素事件执行,最后冒泡!!)
    1、冒泡:(focus, blur, change, submit, reset, select等事件不冒泡)
         根据结构上(非视觉)嵌套关系:son -> father -> grandfather -> ...  一直往上冒泡
    2、捕获:(IE没有。。)
         和冒泡相反,自父元素捕获至事件源元素,第三个参数填true
       (另一种只有IE能用的捕获:div.setCapture()会把页面上的事件都获取到div身上,div.releaseCapture()释放)
    3、取消冒泡:
         W3C:e.stopPropagation(处理函数上传一个参数e,系统会返回一个事件对象,上面包含这个方法)
         IE&chrome:e.cancelBubble = true
    4、阻止默认事件:(表单提交页面刷新,a标签跳转,右键菜单等)
          return false,只对句柄方式绑定的事件(elem.onxxx = function(){})有效
          e.preventDefault(),(a链接的href里面写javascript:void(false)也可以取消a链接默认事件)
          e.returnValue = false,兼容IE
    5、事件对象:e || window.event
    6、事件源对象:event.target || event.srcElement
    7、事件委托:根据冒泡,直接都交给上层处理

          练习:实现一个拖拽函数

        function drag(elem){
            var elem = document.querySelector(elem);
            var disX,
                disY;
            elem.addEventListener('mousedown',function(e){
                var event = e || window.event;
                disX = e.clientX - elem.offsetLeft;
                disY = e.clientY - elem.offsetTop;
                document.addEventListener('mousemove',handle, false)
                elem.addEventListener('mouseup', function(){
                    document.removeEventListener('mousemove',handle, false)
                }, false)
            }, false)
            function handle(e){
                var event = e || window.event;
                elem.style.left = e.clientX - disX + 'px';
                elem.style.top = e.clientY - disY + 'px';
            }
        }

三、事件类型
    1、鼠标类事件:
         1. 需知click只监听左键;up、down区分鼠标左右键;
         2. 事件对象上有button属性,0、1、2分别代表左、中、右;
         3. 在移动端移动端down、up、click等失效。用touchstart、touchmove、touchend代替
    2、键盘类事件:
         1. down、press(会连续触发,比如游戏的前进后退键。down监测所有按键,press监测字符类按键返回ASCII码)、up
         2. String.fromCharCode(unicode码) ,返回字符
    3、文本操作事件:
         1. input:文本但凡变化就触发
         2. change:聚焦和失焦两个状态是否有改变
         3. focus:聚焦
         4. blur:失焦

          完善一个input框

<input type="text" name="username" style="color: #999" value="请输入用户名" onfocus="if(this.value=='请输入用户名'){this.value='';this.style.color='#424242'}" onblur="if(this.value==''){this.value='请输入用户名';this.style.color='#999'}">

    4、窗体类事件:
         1. window.scroll(ie6没有fixed定位,用position:absolute模拟,top = 原top+滚动条的位置)
         2. load(xxx.onload,慢!!!renderTree构建完毕,所有资源加载完成,onload才会执行)
四、关于异步加载:(js会阻塞文档,加载工具方法的js没必要阻塞文档)
         1. domTree,构建时深度优先,domTree构建完成代表所有dom节点解析完毕
         2. cssTree,构建时深度优先
         3. domTree + cssTree = renderTree(渲染引擎开始绘制页面)
            一些操作会引起reflow重排,比如dom节点的删除、添加、宽高,位置变化、offsetWidth、offsetLeft
            还有一些操作会引起repaint重绘,危害略小于重排

    1、异步加载的几种方法:
         1. defer:只有IE能用,<script type="text/javascript" src="" defer="defer"></script>等到dom文档解析完才会被执行
         2. async:<script type="text/javascript" src="" async="async"></script>加载完就执行,只能加载外部脚本
         3. 按需加载

    2、js加载时间线(非常重要)
        创建document对象,开始解析web页面。document.readyState = 'loading'
        遇到link外部css,异步加载
        遇到script外部js,未设置异步的,阻塞文档
        遇到script外部js,设置异步的,异步加载(禁止使用document.write,他能把之前的文档流清空)
        遇到img,正常解析dom,异步加载src
        文档解析完成(domTree完成),document.readyState = 'interactive'
        文档解析完成,设置defer的脚本执行
        文档解析完成,document对象触发DOMContentLoaded(只能用addEventListener绑定,jq的$(document).ready就是这个时候),浏览器转为事件驱动
        整个页面加载完毕,document.readState="complete",即window.onload

以上内容属二哥原创,整理自 "渡一教育Javascript课程" ,一个值得推荐的"渡一教育"。    

07-04 02:50