動手實現你的依賴注入

首先咱們用大白話來理解一次,依賴注入就是我有一個東西,我平時不用,我把這個東西放在你那裏,在我用的時候你拿給我。數組

這個時候咱們已經初步有了概念,咱們在用代碼來消化這個概念bash

首先咱們來先建立一個inject的對象,對象下有個三個屬性分別爲app

  • dependencies這個爲一個數組,用來存放咱們全部的依賴
  • register 這個爲一個函數,用來註冊咱們的依賴
  • resolve 這個用來注入(提取)咱們的依賴
    const inject = {
    dependencies: {},
    register: function(key, value) {
      this.dependencies[key] = value;
    },
    resolve: function(deps, func, scope){
      let arr = [];
      for (let i = 0 ; i < deps.length ; i++) {
           if (this.dependencies.hasOwnProperty(deps[i])) {
              arr.push(this.dependencies[deps[i]])
           }
      }
      return function(){
        func.apply(scope||{},arr);
      }
    },
    }複製代碼
    嗯, 大概就是這個,即然已經把初步的想法實現,咱們如今就來試試到底可不能夠注入

首先實現我有一個東西,而且把這個東西存在你那,那麼咱們用register方法來註冊兩個函數

inject.register('$http', {
  'get': function() {
    return '我是依賴注入的$http下的一個函數';
  }
});
inject.register('$scope', {
  'test': ''
});複製代碼

這個時候我須要用到我前面存放在你那裏東西,你得拿給我ui

let MyController = function($scope,$http){
  console.log(`MyController-result:${$http.get()}`)
}
MyController = inject.resolve(['$scope','$http'],MyController)
MyController(); // MyController-result:我是依賴注入的$http下的一個函數複製代碼

嗯,完美,這樣就簡單的實現咱們的注入,但咱們仔細一下,若是這個時候咱們把這個依賴注入的順序變換一下是報錯的,由於他們是一一對應的,因此咱們還得來改造一下resolve這個方法,this

resolve: function(func, scope){
  let arr = [];
  // 這些正則是在angular的源碼裏找來的
  // 首先把這個函數toString,而後FN_ARGS匹配出來函數的參數,這個參數就是咱們依賴的表
  // 那麼這個時候咱們已經拿到依賴的表了,咱們按照這個表裏取出相對應的函數體給他就完了
  let FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
  let STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
  let fnText = func.toString().replace(STRIP_COMMENTS, '');
  let argDecl = fnText.match(FN_ARGS);
  let deps = argDecl[1].split(',');
  for (let i = 0 ; i < deps.length ; i++) {
       if (this.dependencies.hasOwnProperty(deps[i])) {
          arr.push(this.dependencies[deps[i]])
       }
  }
  return function(){
    func.apply(scope||{},arr);
  }
}複製代碼

固然使用的時候也得改一下spa

let MyController = function($scope,$http){
  console.log(`MyController-result:${$http.get()}`)
}
MyController = inject.resolve(MyController)
MyController(); // MyController-result:我是依賴注入的$http下的一個函數複製代碼

看上去有點像模樣了,這時候我以爲應該有人會提出問題,嗯,對,就是還有問題,咱們知道上線前咱們通常會把項目靜態資源打包,function($scope,$http)會打成相似於function(a,b)這種,那麼這個時候還怎麼去打到對應的函數體呢 ? 咱們再來改寫一下resolve方法code

resolve: function(func, scope) {
  let deps;
  // 若是傳入的函數是一個數組,大概長這樣[a,b,function(a,b){}],那麼咱們刪掉function(){}這部分,只留下咱們的依賴部分,這樣就解決了打包壓縮時的問題
  if (isArray(func)) {
    let last = func.length - 1;
    deps = func.slice(0, last);
    func = func[last]
  } else {
    let FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
    let STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
    let fnText = func.toString().replace(STRIP_COMMENTS, '');
    let argDecl = fnText.match(FN_ARGS);
    deps = argDecl[1].split(',');
  }
  let arr = [];
  for (let i = 0; i < deps.length; i++) {
    if (this.dependencies.hasOwnProperty(deps[i])) {
      arr.push(this.dependencies[deps[i]])
    }
  }
  return function() {
    func.apply(scope || {}, arr);
  }
}複製代碼

固然使用的時候仍是得改改對象

let MyController = ['$scope', '$http', function($scope, $http) {
  console.log(`MyController-result:${$http.get()}`)
}];
MyController = inject.resolve(MyController)
MyController(); // MyController-result:我是依賴注入的$http下的一個函數複製代碼

這樣咱們一個簡易的dependencies inject就完成了,angular的實現思路也是如此ci

相關文章
相關標籤/搜索