第十一周第一天筆記

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

  • 依賴的庫:不依賴任何庫;
  • 使用方法:
    • 為全局函數調用;
    • 系統行為事件綁定:on(ele,type,fn);解除綁定:off(ele,type,fn)
      • 綁定及執行結果:所有瀏覽器兼容,但事件觸發時,fn中this為ele,即元素,默認傳入一個事件對象實參
    • 自定義行為事件綁定:on(ele,type,fn);執行:fire.call(ele,type,e);解綁:off(ele,type,fn);
      • 綁定時on中的ele為元素,fire函數在調用時必須保證里面的this為元素;type自定義行為的開頭必須以my開頭;
      • 綁定及執行結果:fire作為接口放在函數中執行,如果未用on綁定方法,里面無執行函數;當用on綁定方法后,就會在預留接口處執行方法;用于訂閱發布;執行的函數中的this為當前元素;
    • 改變函數的this執行:processThis(fn,thisArg)即:將fn中的this指向改變為thisArg
      • 執行結果:將fn中的this指向改變為thisArg,并給fn傳一個實參e,一般跟事件配合,返回一個匿名函數;
  • 注意:
    • 綁定自定義行為事件時,on里面的參數ele可以是元素也可以是實例對象,但事件庫主要用于給元素綁定系統行為或自定義行為,所以參數ele為元素;一般不設置實例對象;
  • 代碼:
    • 執行代碼:
     <!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函數驗證
         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{//綁定的是系統行為,如click,mousemove等
             //瀏覽器的兼容
             if(ele.addEventListener){
                 ele.addEventListener(type,fn,false);
             }else{//IE瀏覽器
                 if(!ele["on"+type]){
                     ele["on"+type]=[];
                     //將run方法綁定到系統事件池中
                     ele.attachEvent("on"+type,function (e) {
                         run.call(ele,e);//保證run中的this指向為當前元素;在IE瀏覽器下事件觸發,不會給匿名函數傳事件對象實參;
                     })
                 }
                 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函數相當于一個接口,在某個位置執行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);//保證函數執行時,里面的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執行函數,保證函數中的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--;//防止數組塌陷
                 }
             }
         }
     }
     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;//性能優化;
                         }
                     }
                 }
             }
         }
     }
     //改變函數的this執行
     function processThis(fn,thisArg) {
         return function (e) {
             fn.call(thisArg,e);
         }
     }
    

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

  • 依賴的庫:依賴utils庫,用于接口使用時,依賴Event事件庫;
  • 使用方法:
    • 代碼:animate(opt);為全局函數調用;
    • 參數:對象opt
      • 必須傳的參數:1)ele:元素,指需要運動的元素;2)target:屬性值為對象,對象中的鍵值對為目標值;
      • 可傳可不傳的參數:1)duration:運動總時間,默認為2000ms;2)effect:運動方式,可以是字符串,也可以是數字,默認為Linear線性運動;3)callback:不傳不執行,傳了之后執行函數,函數中this被設置為元素;
  • 注意點:在運動結束后,設置一個fire接口,接口的類型為myAnimate,若需要執行操作,可用on在元素身上綁定該行為的方法;fire接口中設置的this為該元素,即綁定的方法執行時,函數中的this為該元素;
  • 執行結果:
    • 目的:一個元素從開始位置(ele)在規定時間(duration)內,以什么樣的運動形式(effect),到達指定目的地(target),執行什么動作(callback或fire接口執行);
  • 代碼:
    • 執行代碼:
     <!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(){
             //此時函數中的this為元素;
             console.log(this.innerHTML);
             this.style.border="5px solid pink";
             this.innerHTML="我成功了,祝賀我吧!";
             this.style.fontSize="10px";
             this.style.lineHeight="10px";
         }
         //綁定myAnimate行為,執行方法
         on(oDiv1,"myAnimate",fn1);
         animate({
             ele:oDiv1,
             target:{
                 left:1000,
                 top:400,
                 opacity: 0.8
             },
             effect:6,
             duration: 2000
             //此時callback可以不用,可以用預留的接口,然后進行綁定執行;
             /*callback:function () {
                 //默認情況下回調函數執行時,this指向window;
                 //在調用時,用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;//如果傳參錯誤,代碼阻斷不執行;
             //1 新建一個對象,里面添加默認樣式
             var defaultOpt={
                 duration: 2000,
                 effect: "Linear"
             };
             //2 將傳入的實參opt,所有屬性賦值給defaultOpt,如果存在,則重新賦值,如果不存在,使用默認值;
             for(var attr in opt){
                 defaultOpt[attr]=opt[attr];
             }
             //總結:defaultOpt的作用是設置默認的屬性,如果傳入的實參里面設置了defaultOpt里面的屬性,就重新賦值,如果沒有設置,就用默認值;
             //下面所有代碼不再使用opt,而使用defaultOpt;
     
             //3 獲取defaultOpt里面的參數
             var ele=defaultOpt.ele;
             var target=defaultOpt.target;
             var duration=defaultOpt.duration;
             var callback=defaultOpt.callback;
             var effect=defaultOpt.effect;
             var tempEffect=null;
             //4 獲取運動形式,計算參數
             //4.1 獲取運動形式:判斷effect的數據類型,滿足下面兩種情況,就執行各自的代碼,如果不滿足,就使用默認值;
             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設置一個函數定義地址,不是函數名;
             }
             //4.2 計算傳入運動形式中的參數
             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 執行回調函數,進行下一步操作
                     callback && callback.call(ele);//當callback存在的時候,執行回調函數,改變其中的this指向為元素;
                     //增加接口,用于綁定多個操作,執行函數,如果不綁定就不會執行方法;
                     fire.call(ele,"myAnimate");
                     //5.2.4 阻斷程序執行
                     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;//將私有函數設置為全局變量;
     })();
    

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

  • 依賴的庫:不依賴任何庫;
  • 使用方法:
    • 代碼:03myAjax(opt);為全局函數調用;
    • 參數:對象opt
      • data:對象,里面的鍵值對為搜索參數;
      • type:get/post/jsonp;
        • get、post用于本地數據獲取,不能跨域獲取;
        • jsonp用于跨域獲取,需注意的是在百度服務器中必須設置jsonp參數為cb才能獲取數據;
  • 代碼:
    • 執行代碼:
     <!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庫封裝代碼:
     //參數:ajax({url:xxx,data:xxx,type:xxx,dataType:xxx,jsonp:xxx,fnLoading:xxx,complete:xxx,success:xxx,error:xxx,timeout})
     //將對象中的屬性名和屬性值轉化為key=val&key=val的形式
     function json2url(obj) {
         //參數:對象,返回值:字符串
         //思路:對象-數組-字符串
         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;
         //參數獲取
         var url=json.url;
         //data屬性值為一個對象,對象中為參數
         var data=json.data||{};
         var type=json.type||"get";
         var jsonp=json.jsonp||"callback";
         var timeout=json.timeout||3000;
         var timer=null;
         //四步:
         //1 創建一個xml對象
         //每個類函數都是window的一個屬性;
         if(window.XMLHttpRequest){
             var xml=new XMLHttpRequest();
         }else{//IE6兼容處理
             var xml=new ActiveXObject("Microsoft.XMLHTTP");
         }
         //2 打開地址;3 發送請求
         //get請求:參數在地址中,在url?的后面,以鍵值對的形式連接;
         //post請求:參數在請求體中,地址url后面不跟參數;
         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":
                 //新建一個全局函數
                 var kbfd="jsonp_"+Math.random();
                 kbfd=kbfd.replace(".","");//函數名中不能存在小數點,所以需要替換
                 window[kbfd]=function (data) {
                     json.success && json.success(data);
                     //卸磨殺驢,干掉script
                     document.body.removeChild(oS);
                     oS=null;
                 };
                 data[jsonp]=kbfd;
                 //創建script標簽,設置其src,通過script發送請求
                 var oS=document.createElement("script");
                 //script中src包含url?參數&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("您的網絡不行啊");
             xml.onreadystatechange=null;
         },timeout);
     }
    

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

  • 依賴的庫:Event事件庫
  • 使用方法:
    • 代碼:var res=new Drag(opt);為實例創建調用;
    • 參數:對象opt;
      • ele:必須穿,為拖拽元素;
    • 執行結果:元素純凈版拖拽,無邊界值判斷,可拖拽到任何地方;
  • 擴展功能:
    • 預留接口:給實例對象綁定了三個自定義行為:myDragDown myDragMove myDragUp
      • 在鼠標按下事件中,添加自定義行為myDragDown
      • 在鼠標移動事件中,添加自定義行為myDragMove
      • 在鼠標抬起事件中,添加自定義行為myDragUp
    • 綁定代碼:res.on("myDragDown",fn1).on("myDragMove",fn2).on("myDragUp",fn3).off("myDragUp",fn3),鏈式操作綁定;
    • 執行結果:綁定的方法函數fn1,fn2等,函數中的this為實例對象,并傳入事件對象e;
  • 代碼:
    • 執行代碼:
     <!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類:給實例對象的自定義行為綁定多個方法,訂閱發布執行
     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函數執行時,里面的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);//保證函數執行時,里面的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上,阻止默認事件發生;
             on(document,"mousemove",this.MOVE);
             on(document,"mouseup",this.UP);
             e.preventDefault();
         }
         this.fire("myDragDown",e);//添加接口,實例對象調用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);//添加接口,實例對象調用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);//添加接口,實例對象調用fire公共方法,自定義行為是myDragUp
     };
    

5 myBind函數封裝

  • 依賴的庫:不依賴任何庫
  • 使用方法:
    • 代碼:fn1.myBind(oDiv,2,3)
    • 調用:函數名調用,myBind為函數類原型上的方法,所有函數均能調用;
    • 參數:
      • 第一個參數:thisArg,必須傳,用于改變函數的this指向,不改變賦值null;
      • 第二個參數:實參,可傳可不傳,如果需要實參則傳,不需要則不傳;
      • 默認傳入一個事件對象實參;多與事件配合;
    • 返回值為一個匿名函數,即函數的預處理;
    • 執行結果:改變fn1函數中的this指向為thisArg,給fn1傳實參,與事件對象配合默認傳入一個事件對象實參;返回一個匿名函數;
  • 代碼:
    • 執行代碼:
     <!DOCTYPE html>
     <html lang="en">
     <head>
         <meta charset="UTF-8">
         <title>myBind函數封裝驗證</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));
             }
         };
     })();
    
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容