自學實現angularjs依賴注入_AngularJS

來源:互聯網
上載者:User

    在用angular依賴注入時,感覺很好用,他的出現是 為了“削減電腦程式的耦合問題” ,我懷著敬畏與好奇的心情,輕輕的走進了angular源碼,看看他到底是怎麼實現的,我也想寫個這麼牛逼的功能。於是就模仿著寫了一個,如果有什麼不對,請大家批評指正。

     其實剛開始的時候我也不知道怎麼下手,源碼中有些確實晦澀難懂,到現在我也沒有看明白,於是我就靜下心想一想,他是怎麼用的,如下所示:

angular.module(/*省略*/) .factory("xxxService", ['xx',function (xx) {  return {    //省略  } }]) .controller('iiController',['xxxService',function(xxxService){  //省略 }]);/*...方法省略..*/

    看看上面strict 模式下的使用方式,先不去看源碼,如何?service重用,controller不重用呢? 我就按照自己的想法建立一個cache用於儲存service,controller 只運行一次,不儲存到cache中。

有了點思路,就把該有的東西先寫了,

(function (global) { function CreateInjector(cache){  this.cache=cache;//用於儲存service的cache } function Angular(){} Angular.module=function(){  var moduleObj={};  return {   injector:new CreateInjector(moduleObj),   factory:function(name,fn){   },   controller:function(name,fn){   }  } }; global.angular = Angular;})(window);

    上面兩個建構函式,一個是建立構造器,一個是angular 的靜態module(不用建立直接用 "建構函式名.方法名",這裡就是想模仿angular.module())方法,這裡angular module 的方法我簡寫了,他也有依賴注入,但是我能力有限,先研究了controller和service的注入。上面的方法名字都是我copy於源碼中的,這裡我就不解釋他們的具體意義了。

由於我們研究的是依賴注入,真正的核心代碼如下:

var ARROW_ARG = /^([^\(]+?)=>/;var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m;var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;function isArray(obj){ return Object.prototype.toString.call(obj) === '[object Array]';}function stringifyFn(fn) { return fn.toString();}function extractArgs(fn) { var fnText = stringifyFn(fn).replace(STRIP_COMMENTS, ''), args= fnText.match(ARROW_ARG) || fnText.match(FN_ARGS); return args[1].split(',');}function CreateInjector(cache){ this.cache=cache;}CreateInjector.prototype={ constructor:CreateInjector, invoke:function(fn,self){  var argsName= extractArgs(fn),argsFn=[];  argsName.forEach(function(arg){   argsFn.push(this.cache[arg]);  },this);  if(isArray(fn)){   return fn[fn.length-1].apply(self,argsFn);  }else{   return fn.apply(self,argsFn);  } }};

其中上面的Regex是複製於源碼中的,代碼原理是:

   (1)把傳來的function toString(),然後用正則match出所傳參數名,用split把參數分割成參數數組;

   (2)迴圈參數數組,在cache中找到此參數名下的函數,push到一個函數數組中;

   (3)利用apply,把函數數組當成參數,去執行函數;

對於所傳的fn, 判斷是數組格式,還是普通的,如果是數組就apply最後的一個值,也就是函數,否則就是fn自己。

   上面的我沒有做錯誤處理,比如注入的找不到等等一些問題,有興趣自己加上吧。

最後所有代碼如下,大家可以複製運行:

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>angular injector Demo</title></head><body><script>(function (global) {  var ARROW_ARG = /^([^\(]+?)=>/;  var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m;  var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;  function isArray(obj){    return Object.prototype.toString.call(obj) === '[object Array]';  }  function stringifyFn(fn) {    return fn.toString();  }  function extractArgs(fn) {    var fnText = stringifyFn(fn).replace(STRIP_COMMENTS, ''),    args= fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);    return args[1].split(',');  }  function CreateInjector(cache){    this.cache=cache;  }  CreateInjector.prototype={    constructor:CreateInjector,    invoke:function(fn,self){      var argsName= extractArgs(fn),argsFn=[];      argsName.forEach(function(arg){        argsFn.push(this.cache[arg]);      },this);      if(isArray(fn)){        return fn[fn.length-1].apply(self,argsFn);      }else{        return fn.apply(self,argsFn);      }    }  };  function Angular(){}  Angular.module=function(){    var moduleObj={};     return {       injector:new CreateInjector(moduleObj),       factory:function(name,fn){         moduleObj[name]=this.injector.invoke(fn);         return this;       },       controller:function(name,fn){         this.injector.invoke(fn);         return this;       }     }  };  global.angular = Angular;})(window);angular.module()  .factory('cacheService',[function(){    return {};  }])  .factory("userInfoService", ['cacheService',function (cacheService) {    return {      getUserInfo:function(){        return cacheService.userInfo;      },      setUserInfo:function(value){        cacheService.userInfo=value;      }    }  }])  .controller('userController',['userInfoService',function(userInfoService){    userInfoService.setUserInfo({id:'qqqq11234',name:'zhangLearing'});    console.log(userInfoService.getUserInfo());  }]);</script></body></html>

謝謝大家!

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援雲棲社區。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.