第十一周第一天筆記

1 事件庫的復習及最終版封裝

  • 依賴的庫:不依賴任何庫;
  • 使用方法:
    • 為全局函數(shù)調(diào)用亩钟;
    • 系統(tǒng)行為事件綁定:on(ele,type,fn);解除綁定:off(ele,type,fn)
      • 綁定及執(zhí)行結(jié)果:所有瀏覽器兼容,但事件觸發(fā)時曹步,fn中this為ele,即元素休讳,默認傳入一個事件對象實參
    • 自定義行為事件綁定:on(ele,type,fn);執(zhí)行:fire.call(ele,type,e);解綁:off(ele,type,fn)讲婚;
      • 綁定時on中的ele為元素,fire函數(shù)在調(diào)用時必須保證里面的this為元素俊柔;type自定義行為的開頭必須以my開頭筹麸;
      • 綁定及執(zhí)行結(jié)果:fire作為接口放在函數(shù)中執(zhí)行,如果未用on綁定方法雏婶,里面無執(zhí)行函數(shù)物赶;當用on綁定方法后,就會在預留接口處執(zhí)行方法留晚;用于訂閱發(fā)布酵紫;執(zhí)行的函數(shù)中的this為當前元素;
    • 改變函數(shù)的this執(zhí)行:processThis(fn,thisArg)即:將fn中的this指向改變?yōu)閠hisArg
      • 執(zhí)行結(jié)果:將fn中的this指向改變?yōu)閠hisArg错维,并給fn傳一個實參e,一般跟事件配合奖地,返回一個匿名函數(shù);
  • 注意:
    • 綁定自定義行為事件時赋焕,on里面的參數(shù)ele可以是元素也可以是實例對象参歹,但事件庫主要用于給元素綁定系統(tǒng)行為或自定義行為,所以參數(shù)ele為元素隆判;一般不設置實例對象犬庇;
  • 代碼:
    • 執(zhí)行代碼:
     <!DOCTYPE html>
     <html lang="en">
     <head>
         <meta charset="UTF-8">
         <title>事件庫最終版封裝</title>
         <style>
             body{
                 height: 1000px;
             }
             div{
                 width: 200px;
                 height: 200px;
                 background-color: red;
             }
         </style>
     </head>
     <body>
     <div id="div1">111</div>
     <script src="復習JS庫/01Event.js"></script>
     <script>
         var oDiv=document.getElementById("div1");
         on(oDiv,"mymeinv",fn1);
         on(oDiv,"mymeinv",fn2);
         on(oDiv,"mymeinv",fn3);
         //off(oDiv,"mymeinv",fn3);
         function fn1(e) {
             console.log(this.innerHTML);
             console.log(e.pageY);
         }
         function fn2() {
             console.log(2);
         }
         function fn3() {
             console.log(3);
         }
         on(oDiv,"click",fn4);
         function fn4(e){
             fire.call(this,"mymeinv",e);
         }
         //processThis函數(shù)驗證
         function add(e) {
             console.log(this);
             console.log(e.type);
         }
         on(oDiv,"click",processThis(add,oDiv));
     </script>
     </body>
     </html>
    
    • 事件庫終極版封裝
     function on(ele,type,fn) {
         if(/^my/gi.test(type)){//綁定的是自定義行為,必須以my開頭
             //事件庫中ele均為元素
             if(!ele[type]){
                 ele[type]=[];
             }
             var b=ele[type];
             if(b.length){
                 for(var i=0; i<b.length; i++){
                     if(b[i]===fn) return;
                 }
             }
             b.push(fn);
         }else{//綁定的是系統(tǒng)行為侨嘀,如click,mousemove等
             //瀏覽器的兼容
             if(ele.addEventListener){
                 ele.addEventListener(type,fn,false);
             }else{//IE瀏覽器
                 if(!ele["on"+type]){
                     ele["on"+type]=[];
                     //將run方法綁定到系統(tǒng)事件池中
                     ele.attachEvent("on"+type,function (e) {
                         run.call(ele,e);//保證run中的this指向為當前元素臭挽;在IE瀏覽器下事件觸發(fā),不會給匿名函數(shù)傳事件對象實參咬腕;
                     })
                 }
                 var a=ele["on"+type];
                 //去重處理欢峰,避免重復綁定
                 if(a.length){
                     for(var i=0; i<a.length; i++){
                         if(a[i]===fn) return;
                     }
                 }
                 a.push(fn);
             }
         }
     }
     //fire函數(shù)相當于一個接口,在某個位置執(zhí)行on綁定的type行為上的所有方法;
     function fire(type,e) {
         //fire中的this可以指元素赤赊,也可以指實例對象,與on中相對應煞赢;
         var b=this[type] || [];
         if(b.length){
             for(var i=0; i<b.length; i++){
                 if(typeof b[i]==="function"){
                     b[i].call(this,e);//保證函數(shù)執(zhí)行時抛计,里面的this為當前this,即為元素照筑,并傳入實參e;
                 }else{
                     b.splice(i,1);
                     i--;
                 }
             }
         }
     }
     function run(e) {
         e= e || window.event;
         //e的兼容處理
         e.target=e.srcElement;
         e.pageX=(document.documentElement.scrollLeft || document.body.scrollLeft)+e.clientX;
         e.pageY=(document.documentElement.scrollTop || document.body.scrollTop)+e.clientY;
         //阻止默認事件
         e.preventDefault=function () {
             e.returnValue=false;
         };
         //阻止冒泡
         e.stopPropagation=function () {
             e.cancelBubble=true;
         };
         //遍歷run執(zhí)行函數(shù)吹截,保證函數(shù)中的this為當前元素,而且給其傳實參e
         var a=this["on"+e.type];//this為當前元素
         if(a.length){
             for(var i=0; i<a.length; i++){
                 if(typeof a[i]==="function"){
                     a[i].call(this,e);
                 }else{
                     a.splice(i,1);
                     i--;//防止數(shù)組塌陷
                 }
             }
         }
     }
     function off(ele,type,fn) {
         if(/^my/gi.test(type)){
             var b=ele[type];
             if(b.length){
                 for(var i=0; i<b.length; i++){
                     if(b[i]===fn){
                         b[i]=null;
                         break;
                     }
                 }
             }
         }else{
             if(ele.removeEventListener){
                 ele.removeEventListener(type,fn,false);
             }else{
                 var a=ele["on"+type];
                 if(a.length){
                     for(var i=0; i<a.length; i++){
                         if(a[i]===fn){
                             a[i]=null;
                             break;//性能優(yōu)化凝危;
                         }
                     }
                 }
             }
         }
     }
     //改變函數(shù)的this執(zhí)行
     function processThis(fn,thisArg) {
         return function (e) {
             fn.call(thisArg,e);
         }
     }
    

2 運動庫的復習及最終版封裝

  • 依賴的庫:依賴utils庫波俄,用于接口使用時,依賴Event事件庫蛾默;
  • 使用方法:
    • 代碼:animate(opt);為全局函數(shù)調(diào)用懦铺;
    • 參數(shù):對象opt
      • 必須傳的參數(shù):1)ele:元素,指需要運動的元素支鸡;2)target:屬性值為對象冬念,對象中的鍵值對為目標值;
      • 可傳可不傳的參數(shù):1)duration:運動總時間牧挣,默認為2000ms急前;2)effect:運動方式,可以是字符串瀑构,也可以是數(shù)字裆针,默認為Linear線性運動;3)callback:不傳不執(zhí)行寺晌,傳了之后執(zhí)行函數(shù)世吨,函數(shù)中this被設置為元素;
  • 注意點:在運動結(jié)束后折剃,設置一個fire接口另假,接口的類型為myAnimate,若需要執(zhí)行操作怕犁,可用on在元素身上綁定該行為的方法边篮;fire接口中設置的this為該元素,即綁定的方法執(zhí)行時奏甫,函數(shù)中的this為該元素戈轿;
  • 執(zhí)行結(jié)果:
    • 目的:一個元素從開始位置(ele)在規(guī)定時間(duration)內(nèi),以什么樣的運動形式(effect)阵子,到達指定目的地(target)思杯,執(zhí)行什么動作(callback或fire接口執(zhí)行);
  • 代碼:
    • 執(zhí)行代碼:
     <!DOCTYPE html>
     <html lang="en">
     <head>
         <meta charset="UTF-8">
         <title>運動庫驗證</title>
         <style>
             *{
                 margin: 0;
                 padding: 0;
             }
             #div1{
                 width: 80px;
                 height: 80px;
                 background-color: red;
                 line-height: 80px;
                 text-align: center;
                 position: absolute;
                 top: 10px;
                 left:200px;
                 opacity: 0.1;
                 filter: alpha(opacity=10);
             }
             #div2{
                 width: 1px;
                 height: 500px;
                 margin-top: 10px;
                 background-color: blue;
                 position: absolute;
                 top: 10px;
                 left: 1100px;
             }
         </style>
     </head>
     <body>
     <div id="div1">物體</div>
     <div id="div2"></div>
     <script src="復習JS庫/00utils.js"></script>
     <script src="復習JS庫/01Event.js"></script>
     <script src="復習JS庫/02Animate.js"></script>
     <script>
         var oDiv1=document.getElementById("div1");
         function fn1(){
             //此時函數(shù)中的this為元素;
             console.log(this.innerHTML);
             this.style.border="5px solid pink";
             this.innerHTML="我成功了色乾,祝賀我吧誊册!";
             this.style.fontSize="10px";
             this.style.lineHeight="10px";
         }
         //綁定myAnimate行為,執(zhí)行方法
         on(oDiv1,"myAnimate",fn1);
         animate({
             ele:oDiv1,
             target:{
                 left:1000,
                 top:400,
                 opacity: 0.8
             },
             effect:6,
             duration: 2000
             //此時callback可以不用暖璧,可以用預留的接口案怯,然后進行綁定執(zhí)行;
             /*callback:function () {
                 //默認情況下回調(diào)函數(shù)執(zhí)行時澎办,this指向window;
                 //在調(diào)用時嘲碱,用call改變this指向為ele;
                 this.style.backgroundColor="yellow";
             }*/
         })
     </script>
     </body>
     </html>
    
    • 封裝代碼:
     (function () {
         //運動形式對象
         var gbEffect= {
             Linear: function (t, b, c, d){  //勻速
                 return c*t/d + b;
             },
             EaseIn: function(t, b, c, d){  //加速曲線
                 return c*(t/=d)*t + b;
             },
             EaseOut: function(t, b, c, d){  //減速曲線
                 return -c *(t/=d)*(t-2) + b;
             },
             EaseBoth: function(t, b, c, d){  //加速減速曲線
                 if ((t/=d/2) < 1) {
                     return c/2*t*t + b;
                 }
                 return -c/2 * ((--t)*(t-2) - 1) + b;
             },
             EaseInStrong: function(t, b, c, d){  //加加速曲線
                 return c*(t/=d)*t*t*t + b;
             },
             EaseOutStrong: function(t, b, c, d){  //減減速曲線
                 return -c * ((t=t/d-1)*t*t*t - 1) + b;
             },
             EaseBothStrong: function(t, b, c, d){  //加加速減減速曲線
                 if ((t/=d/2) < 1) {
                     return c/2*t*t*t*t + b;
                 }
                 return -c/2 * ((t-=2)*t*t*t - 2) + b;
             },
             Elastic:{
                 In: function(t, b, c, d, a, p){  //正弦衰減曲線(彈動漸入)
                     if (t === 0) {
                         return b;
                     }
                     if ( (t /= d) == 1 ) {
                         return b+c;
                     }
                     if (!p) {
                         p=d*0.3;
                     }
                     if (!a || a < Math.abs(c)) {
                         a = c;
                         var s = p/4;
                     } else {
                         var s = p/(2*Math.PI) * Math.asin (c/a);
                     }
                     return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
                 },
                 Out: function(t, b, c, d, a, p){    //正弦增強曲線(彈動漸出)
                     if (t === 0) {
                         return b;
                     }
                     if ( (t /= d) == 1 ) {
                         return b+c;
                     }
                     if (!p) {
                         p=d*0.3;
                     }
                     if (!a || a < Math.abs(c)) {
                         a = c;
                         var s = p / 4;
                     } else {
                         var s = p/(2*Math.PI) * Math.asin (c/a);
                     }
                     return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
                 },
                 Both: function(t, b, c, d, a, p){
                     if (t === 0) {
                         return b;
                     }
                     if ( (t /= d/2) == 2 ) {
                         return b+c;
                     }
                     if (!p) {
                         p = d*(0.3*1.5);
                     }
                     if ( !a || a < Math.abs(c) ) {
                         a = c;
                         var s = p/4;
                     }
                     else {
                         var s = p/(2*Math.PI) * Math.asin (c/a);
                     }
                     if (t < 1) {
                         return - 0.5*(a*Math.pow(2,10*(t-=1)) *
                             Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
                     }
                     return a*Math.pow(2,-10*(t-=1)) *
                         Math.sin( (t*d-s)*(2*Math.PI)/p )*0.5 + c + b;
                 }
     
             },
             Back:{
                 In: function(t, b, c, d, s){     //回退加速(回退漸入)
                     if (typeof s == 'undefined') {
                         s = 1.70158;
                     }
                     return c*(t/=d)*t*((s+1)*t - s) + b;
                 },
                 Out: function(t, b, c, d, s){
                     if (typeof s == 'undefined') {
                         s = 3.70158;  //回縮的距離
                     }
                     return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
                 },
                 Both: function(t, b, c, d, s){
                     if (typeof s == 'undefined') {
                         s = 1.70158;
                     }
                     if ((t /= d/2 ) < 1) {
                         return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
                     }
                     return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
                 }
             },
             Bounce:{
                 In: function(t, b, c, d){    //彈球減振(彈球漸出)
                     return c - gbEffect.Bounce.Out(d-t, 0, c, d) + b;
                 },
                 Out: function(t, b, c, d){
                     if ((t/=d) < (1/2.75)) {
                         return c*(7.5625*t*t) + b;
                     } else if (t < (2/2.75)) {
                         return c*(7.5625*(t-=(1.5/2.75))*t + 0.75) + b;
                     } else if (t < (2.5/2.75)) {
                         return c*(7.5625*(t-=(2.25/2.75))*t + 0.9375) + b;
                     }
                     return c*(7.5625*(t-=(2.625/2.75))*t + 0.984375) + b;
                 },
                 Both: function(t, b, c, d){
                     if (t < d/2) {
                         return gbEffect.Bounce.In(t*2, 0, c, d) * 0.5 + b;
                     }
                     return gbEffect.Bounce.Out(t*2-d, 0, c, d) * 0.5 + c*0.5 + b;
                 }
             }
         };
         var gbEffectAry=["Linear","EaseIn","EaseOut","EaseBoth","EaseInStrong","EaseOutStrong","EaseBothStrong","Elastic-In","Elastic-Out","Elastic-Both","Back-In","Back-Out","Back-Both","Bounce-In","Bounce-Out","Bounce-Both"];
         //運動庫封裝
         function animate(opt) {
             //0 對傳入的實參值進行判斷局蚀;
             opt=opt || {};
             if(!opt.ele) return;//如果傳參錯誤麦锯,代碼阻斷不執(zhí)行;
             //1 新建一個對象琅绅,里面添加默認樣式
             var defaultOpt={
                 duration: 2000,
                 effect: "Linear"
             };
             //2 將傳入的實參opt扶欣,所有屬性賦值給defaultOpt,如果存在千扶,則重新賦值宵蛀,如果不存在,使用默認值县貌;
             for(var attr in opt){
                 defaultOpt[attr]=opt[attr];
             }
             //總結(jié):defaultOpt的作用是設置默認的屬性术陶,如果傳入的實參里面設置了defaultOpt里面的屬性,就重新賦值煤痕,如果沒有設置梧宫,就用默認值;
             //下面所有代碼不再使用opt摆碉,而使用defaultOpt;
     
             //3 獲取defaultOpt里面的參數(shù)
             var ele=defaultOpt.ele;
             var target=defaultOpt.target;
             var duration=defaultOpt.duration;
             var callback=defaultOpt.callback;
             var effect=defaultOpt.effect;
             var tempEffect=null;
             //4 獲取運動形式塘匣,計算參數(shù)
             //4.1 獲取運動形式:判斷effect的數(shù)據(jù)類型,滿足下面兩種情況巷帝,就執(zhí)行各自的代碼忌卤,如果不滿足,就使用默認值楞泼;
             var ary=gbEffectAry;
             if(typeof effect==="number"){
                 ary=ary[effect%ary.length].split("-");
                 tempEffect=ary.length>=2?gbEffect[ary[0]][ary[1]]:gbEffect[ary[0]];
             }else if(typeof effect==="object"){
                 tempEffect=effect.length>=2?gbEffect[effect[0]][effect[1]]:gbEffect[effect[0]];
             }else if(typeof effect==="string"){
                 tempEffect=gbEffect[effect];//此時tempEffect設置一個函數(shù)定義地址驰徊,不是函數(shù)名;
             }
             //4.2 計算傳入運動形式中的參數(shù)
             var begin={},change={};
             for(var attr in target){
                 begin[attr]=utils.css(ele,attr);
                 change[attr]=target[attr]-begin[attr];
             }
             var time=0;
     
             //5 添加定時器
             var timer=setInterval(function () {
                 //5.1 變量累加
                 time+=30;
                 //5.2 邊界值判斷
                 if(time>=duration){
                     //5.2.1 設置邊界值
                     utils.css(ele,target);
                     //5.2.2 停止定時器
                     clearInterval(timer);
                     //5.2.3 執(zhí)行回調(diào)函數(shù)堕阔,進行下一步操作
                     callback && callback.call(ele);//當callback存在的時候棍厂,執(zhí)行回調(diào)函數(shù),改變其中的this指向為元素超陆;
                     //增加接口牺弹,用于綁定多個操作,執(zhí)行函數(shù),如果不綁定就不會執(zhí)行方法张漂;
                     fire.call(ele,"myAnimate");
                     //5.2.4 阻斷程序執(zhí)行
                     return;
                 }
                 //5.3 獲取最新位置及設置最新位置
                 for(var attr in change){
                     //5.3.1 運動方式獲取最新位置晶默;
                     var cur=tempEffect(time,begin[attr],change[attr],duration);
                     //5.3.2 分別設置最新位置
                     utils.css(ele,attr,cur);
                 }
             },30)
     
         }
         window.animate=animate;//將私有函數(shù)設置為全局變量;
     })();
    

3 ajax庫的復習及最終版封裝

  • 依賴的庫:不依賴任何庫航攒;
  • 使用方法:
    • 代碼:03myAjax(opt);為全局函數(shù)調(diào)用荤胁;
    • 參數(shù):對象opt
      • data:對象,里面的鍵值對為搜索參數(shù)屎债;
      • type:get/post/jsonp;
        • get垢油、post用于本地數(shù)據(jù)獲取盆驹,不能跨域獲取滩愁;
        • jsonp用于跨域獲取躯喇,需注意的是在百度服務器中必須設置jsonp參數(shù)為cb才能獲取數(shù)據(jù);
  • 代碼:
    • 執(zhí)行代碼:
     <!DOCTYPE html>
     <html lang="en">
     <head>
         <meta charset="UTF-8">
         <title>封裝的ajax</title>
     </head>
     <body>
     <script src="JS庫終極版/03myAjax.jsjs"></script>
     <script>
         03myAjax({
             url:"https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su",
             data:{wd:"zhouxingchi"},
             type:"jsonp",
             dataType:"json",
             jsonp:"cb",//此處必須設置jsonp為cb硝枉,才能使用
             success:function (data) {
                 console.log(data);
             }
         });
     </script>
     </body>
     </html>
    
    • JS庫封裝代碼:
     //參數(shù):ajax({url:xxx,data:xxx,type:xxx,dataType:xxx,jsonp:xxx,fnLoading:xxx,complete:xxx,success:xxx,error:xxx,timeout})
     //將對象中的屬性名和屬性值轉(zhuǎn)化為key=val&key=val的形式
     function json2url(obj) {
         //參數(shù):對象廉丽,返回值:字符串
         //思路:對象-數(shù)組-字符串
         obj.t=Math.random();//避免緩存
         var ary=[];
         //遍歷對象
         for(var attr in obj){
             ary.push(attr+"="+obj[attr]);
         }
         return ary.join("&");
     }
     function jsonParse(strJson) {
         return "JSON" in window?JSON.parse(strJson):eval("("+strJson+")");
     }
     function 03myAjax(json) {
         json=json||{};
         //如果json中請求地址url不存在
         if(!json.url) return;
         //參數(shù)獲取
         var url=json.url;
         //data屬性值為一個對象,對象中為參數(shù)
         var data=json.data||{};
         var type=json.type||"get";
         var jsonp=json.jsonp||"callback";
         var timeout=json.timeout||3000;
         var timer=null;
         //四步:
         //1 創(chuàng)建一個xml對象
         //每個類函數(shù)都是window的一個屬性妻味;
         if(window.XMLHttpRequest){
             var xml=new XMLHttpRequest();
         }else{//IE6兼容處理
             var xml=new ActiveXObject("Microsoft.XMLHTTP");
         }
         //2 打開地址正压;3 發(fā)送請求
         //get請求:參數(shù)在地址中,在url?的后面责球,以鍵值對的形式連接焦履;
         //post請求:參數(shù)在請求體中,地址url后面不跟參數(shù)雏逾;
         switch(type.toLowerCase()){
             case "get":
                 xml.open("get",url+"?"+json2url(data),true);
                 xml.send(null);
                 break;
             case "post":
                 xml.open("post",url,true);
                 xml.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
                 xml.send(json2url(data));
                 break;
             case "jsonp":
                 //新建一個全局函數(shù)
                 var kbfd="jsonp_"+Math.random();
                 kbfd=kbfd.replace(".","");//函數(shù)名中不能存在小數(shù)點嘉裤,所以需要替換
                 window[kbfd]=function (data) {
                     json.success && json.success(data);
                     //卸磨殺驢,干掉script
                     document.body.removeChild(oS);
                     oS=null;
                 };
                 data[jsonp]=kbfd;
                 //創(chuàng)建script標簽栖博,設置其src屑宠,通過script發(fā)送請求
                 var oS=document.createElement("script");
                 //script中src包含url?參數(shù)&cb=kbfd
                 oS.src=url+"?"+json2url(data);
                 //script必須插入到頁面的底部
                 document.body.appendChild(oS);
                 break;
         }
         //響應請求之前的準備
         json.fnLoading && json.fnLoading();
         //4 響應請求
         xml.onreadystatechange=function () {
             if(xml.readyState===4){
                 //請求成功
                 json.complete && json.complete();
                 clearTimeout(timer);
                 //判斷后臺響應成功還是失敗仇让;
                 if(/^2\d{2}$/.test(xml.status)){//響應成功
                     if(json.dataType==="json"){
                         json.success && json.success(jsonParse(xml.responseText));
                     }else{
                         json.success && json.success(xml.responseText);
                     }
                 }else{//響應失敗
                         json.error && json.error(xml.status);
                 }
             }
     
         };
         if(type==="jsonp") return;
         //5 等待超時
         timer=setTimeout(function () {
             alert("您的網(wǎng)絡不行啊");
             xml.onreadystatechange=null;
         },timeout);
     }
    

4 拖拽庫復習及最終版封裝

  • 依賴的庫:Event事件庫
  • 使用方法:
    • 代碼:var res=new Drag(opt);為實例創(chuàng)建調(diào)用典奉;
    • 參數(shù):對象opt;
      • ele:必須穿,為拖拽元素丧叽;
    • 執(zhí)行結(jié)果:元素純凈版拖拽秋柄,無邊界值判斷,可拖拽到任何地方蠢正;
  • 擴展功能:
    • 預留接口:給實例對象綁定了三個自定義行為:myDragDown myDragMove myDragUp
      • 在鼠標按下事件中骇笔,添加自定義行為myDragDown
      • 在鼠標移動事件中,添加自定義行為myDragMove
      • 在鼠標抬起事件中,添加自定義行為myDragUp
    • 綁定代碼:res.on("myDragDown",fn1).on("myDragMove",fn2).on("myDragUp",fn3).off("myDragUp",fn3)笨触,鏈式操作綁定懦傍;
    • 執(zhí)行結(jié)果:綁定的方法函數(shù)fn1,fn2等,函數(shù)中的this為實例對象芦劣,并傳入事件對象e;
  • 代碼:
    • 執(zhí)行代碼:
     <!DOCTYPE html>
     <html lang="en">
     <head>
         <meta charset="UTF-8">
         <title>拖拽Drag庫封裝驗證</title>
         <style>
             div{
                 width: 200px;
                 height: 200px;
                 background-color: red;
                 position: absolute;
                 left: 0;
                 top: 0;
             }
         </style>
     </head>
     <body>
     <div id="div">111</div>
     <script src="JS庫終極版/01Event.js"></script>
     <script src="JS庫終極版/04Drag.js"></script>
     <script>
         var oDiv=document.getElementById("div");
         var res=new Drag({
             ele:oDiv
         });
         res.on("myDragDown",fn1).on("myDragMove",fn2).on("myDragUp",fn3).off("myDragUp",fn3);//鏈式操作
         function fn1() {
             console.log(this);//this為實例
             console.log(1)
         }
         function fn2() {
             console.log(2)
         }
         function fn3() {
             console.log(3)
         }
     </script>
     </body>
     </html>
    
    • JS封裝代碼:
     //EventEmitter類:給實例對象的自定義行為綁定多個方法粗俱,訂閱發(fā)布執(zhí)行
     function EventEmitter() {}
     EventEmitter.prototype.on=function (type,fn) {
         if(!this[type]){
             this[type]=[];
         }
         var a=this[type];
         if(a.length){
             for(var i=0; i<a.length; i++){
                 if(a[i]===fn) return;
             }
         }
         a.push(fn);
         return this;//進行鏈式操作
     };
     EventEmitter.prototype.fire=function(type,e){
         //保證fire函數(shù)執(zhí)行時,里面的this為實例對象虚吟;
         var a=this[type] || [];
         if(a.length){
             for(var i=0; i<a.length; i++){
                 if(typeof a[i]==="function"){
                     a[i].call(this,e);//保證函數(shù)執(zhí)行時寸认,里面的this為實例對象,并傳事件對象實參串慰;
                 }else{
                     a.splice(i,1);
                     i--;
                 }
             }
         }
     };
     EventEmitter.prototype.off=function (type,fn) {
         var a=this[type];
         if(a.length){
             for(var i=0; i<a.length; i++){
                 if(a[i]===fn){
                     a[i]=null;
                     break;
                 }
             }
         }
     };
     //Drag類:拖拽
     function Drag(opt) {
         opt=opt||{};
         if(!opt.ele) return;
         this.ele=opt.ele;
         this.disX=null;
         this.disY=null;
         this.DOWN=null;
         this.MOVE=null;
         this.UP=null;
         this.init();
     }
     //原型鏈繼承
     Drag.prototype=new EventEmitter();
     //原型鏈繼承后偏塞,原型上沒有自己類的constructor屬性,需要重新設置
     Drag.prototype.constructor=Drag;
     //原型上公共方法
     Drag.prototype.init=function () {
         //綁定down事件邦鲫;
         this.DOWN=processThis(this.down,this);
         on(this.ele,"mousedown",this.DOWN);
     };
     Drag.prototype.down=function (e) {
         //獲取鼠標相對于元素的位置disX,disY
         this.disX=e.clientX-this.ele.offsetLeft;
         this.disY=e.clientY-this.ele.offsetTop;
         //綁定move,up事件
         this.MOVE=processThis(this.move,this);
         this.UP=processThis(this.up,this);
         if(this.ele.setCapture){//IE瀏覽器
             this.ele.setCapture();//焦點捕獲
             on(this.ele,"mousemove",this.MOVE);
             on(this.ele,"mouseup",this.UP);
         }else{//標準瀏覽器
             //將事件綁定到document上灸叼,阻止默認事件發(fā)生;
             on(document,"mousemove",this.MOVE);
             on(document,"mouseup",this.UP);
             e.preventDefault();
         }
         this.fire("myDragDown",e);//添加接口庆捺,實例對象調(diào)用fire公共方法古今,自定義行為是myDragDown
     };
     Drag.prototype.move=function (e) {
         //獲取新位置,無邊界值判斷
         var l=e.clientX-this.disX;
         var t=e.clientY-this.disY;
         //設置新位置
         this.ele.style.left=l+"px";
         this.ele.style.top=t+"px";
         this.fire("myDragMove",e);//添加接口滔以,實例對象調(diào)用fire公共方法捉腥,自定義行為是myDragMove
     };
     Drag.prototype.up=function (e) {
         if(this.ele.releaseCapture){
             this.ele.releaseCapture();//釋放焦點捕獲;
             off(this.ele,"mousemove",this.MOVE);
             off(this.ele,"mouseup",this.UP);
         }else{
             off(document,"mousemove",this.MOVE);
             off(document,"mouseup",this.UP);
         }
         this.fire("myDragUp",e);//添加接口你画,實例對象調(diào)用fire公共方法但狭,自定義行為是myDragUp
     };
    

5 myBind函數(shù)封裝

  • 依賴的庫:不依賴任何庫
  • 使用方法:
    • 代碼:fn1.myBind(oDiv,2,3)
    • 調(diào)用:函數(shù)名調(diào)用撬即,myBind為函數(shù)類原型上的方法立磁,所有函數(shù)均能調(diào)用;
    • 參數(shù):
      • 第一個參數(shù):thisArg剥槐,必須傳唱歧,用于改變函數(shù)的this指向,不改變賦值null;
      • 第二個參數(shù):實參粒竖,可傳可不傳颅崩,如果需要實參則傳,不需要則不傳蕊苗;
      • 默認傳入一個事件對象實參沿后;多與事件配合;
    • 返回值為一個匿名函數(shù)朽砰,即函數(shù)的預處理尖滚;
    • 執(zhí)行結(jié)果:改變fn1函數(shù)中的this指向為thisArg喉刘,給fn1傳實參,與事件對象配合默認傳入一個事件對象實參漆弄;返回一個匿名函數(shù)睦裳;
  • 代碼:
    • 執(zhí)行代碼:
     <!DOCTYPE html>
     <html lang="en">
     <head>
         <meta charset="UTF-8">
         <title>myBind函數(shù)封裝驗證</title>
         <style>
             div{
                 width: 200px;
                 height: 200px;
                 background-color: red;
             }
         </style>
     </head>
     <body>
     <div id="div1">1111</div>
     <script src="JS庫終極版/05myBind.js"></script>
     <script>
         var oDiv=document.getElementById("div1");
         function fn1(n,m,e){
             console.log(this.innerHTML);
             console.log(n+m);
             console.log(e.pageX);
         }
         oDiv.onclick=fn1.myBind(oDiv,2,3);
     </script>
     </body>
     </html>
    
    • JS封裝代碼:
     (function () {
         Function.prototype.myBind=function (thisArg) {
             var outArg=[].slice.call(arguments,1);
             if("bind" in Function.prototype){
                 return this.bind.apply(this,[thisArg].concat(outArg));
             }
             var _this=this;
             return function (e) {
                 e=arguments.length===0?window.event:e;
                 //IE瀏覽器下的兼容處理
                 e.target=e.srcElement;
                 e.pageX=(document.documentElement.scrollLeft ||document.body.scrollLeft)+e.clientX;
                 e.pageY=(document.documentElement.scrollTop || document.body.scrollTop)+e.clientY;
                 //阻止默認事件
                 e.preventDefault=function () {
                     e.returnValue=false;
                 };
                 //阻止冒泡
                 e.stopPropagation=function () {
                     e.cancelBubble=true;
                 };
                 return _this.apply(thisArg,outArg.concat(e));
             }
         };
     })();
    
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市撼唾,隨后出現(xiàn)的幾起案子廉邑,更是在濱河造成了極大的恐慌,老刑警劉巖倒谷,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛛蒙,死亡現(xiàn)場離奇詭異,居然都是意外死亡渤愁,警方通過查閱死者的電腦和手機牵祟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來猴伶,“玉大人,你說我怎么就攤上這事塌西∷妫” “怎么了?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵捡需,是天一觀的道長办桨。 經(jīng)常有香客問我,道長站辉,這世上最難降的妖魔是什么呢撞? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮饰剥,結(jié)果婚禮上殊霞,老公的妹妹穿的比我還像新娘。我一直安慰自己汰蓉,他們只是感情好绷蹲,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著顾孽,像睡著了一般祝钢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上若厚,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天拦英,我揣著相機與錄音,去河邊找鬼测秸。 笑死疤估,一個胖子當著我的面吹牛灾常,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播做裙,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼岗憋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了锚贱?” 一聲冷哼從身側(cè)響起仔戈,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拧廊,沒想到半個月后监徘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡吧碾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年凰盔,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片倦春。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡户敬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出睁本,到底是詐尸還是另有隱情尿庐,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布呢堰,位于F島的核電站抄瑟,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏枉疼。R本人自食惡果不足惜皮假,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望骂维。 院中可真熱鬧惹资,春花似錦、人聲如沸航闺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽来颤。三九已至汰扭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間福铅,已是汗流浹背萝毛。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留滑黔,地道東北人笆包。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓环揽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親庵佣。 傳聞我的和親對象是個殘疾皇子歉胶,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容