成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

[ AngularJS ] 自己實(shí)現(xiàn)一個(gè)簡(jiǎn)單的依賴(lài)注入

seasonley / 1841人閱讀

摘要:我們開(kāi)始使用的時(shí)候,它的雙向數(shù)據(jù)綁定是最讓我們印象深刻的,那第二個(gè)就應(yīng)該算是它的那神奇的依賴(lài)注入的功能了。來(lái)實(shí)現(xiàn)依賴(lài)注入現(xiàn)在大部分的框架都提供依賴(lài)注入機(jī)制的模塊,可能會(huì)叫做。

  

我們開(kāi)始使用AngularJS的時(shí)候,它的雙向數(shù)據(jù)綁定是最讓我們印象深刻的,那第二個(gè)就應(yīng)該算是它的那神奇的依賴(lài)注入的功能了。

舉個(gè)栗子
function myController = ($scope, $http){
    $http.get("users/users.json").success(function(data){
        $scope.users = data;
    })
}

這是一個(gè)典型的angularjs的控制器,他發(fā)送了一個(gè)http請(qǐng)求,從后臺(tái)獲取json數(shù)據(jù),然后把他傳遞給當(dāng)前作用域。你會(huì)發(fā)現(xiàn),我們并沒(méi)有執(zhí)行這個(gè)myController函數(shù)(我們沒(méi)有機(jī)會(huì)給它傳遞參數(shù)),其實(shí),是angular這個(gè)框架幫我們做了;那么,$scope, $http這些變量從哪里來(lái)的呢? 這是angular的一個(gè)非??岬奶匦?,我們一步步來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的注入器,從而知道它是怎么實(shí)現(xiàn)的。

傳統(tǒng)的方式

現(xiàn)在,我們有一個(gè)js函數(shù)去把用戶列表展示在網(wǎng)頁(yè)上,那么這個(gè)函數(shù)就需要從ajax獲取過(guò)來(lái)的數(shù)據(jù)和用于展示數(shù)據(jù)的DOM元素。為了簡(jiǎn)單點(diǎn),我們直接用靜態(tài)數(shù)據(jù)了來(lái)代替ajax的http請(qǐng)求:

var data = ["John", "Steve", "David"];
var body = document.querySelector("body");
var ajaxFn = {
  get: function(path, cb) {
    console.log(path + " requested");
    cb(data);
  }
}

我們把body標(biāo)簽作為列表的容器,ajaxFn是模擬ajax請(qǐng)求的對(duì)象,data是一個(gè)包含所有用戶的數(shù)組。下面來(lái)使用:

var displayUsers = function(domEl, ajax) {
  ajax.get("/api/users", function(users) {
    var html = "";
    for(var i=0; i < users.length; i++) {
      html += "

" + users[i] + "

"; } domEl.innerHTML = html; }); }

很明顯,我們運(yùn)行displayUsers(body, ajaxFn),我們將會(huì)看到三個(gè)用戶名顯示在網(wǎng)頁(yè)上,同時(shí)控制臺(tái)輸出了/api/users requested。那這樣的話,我們可以認(rèn)為我們的displayUsers函數(shù)有兩個(gè)依賴(lài),bodyajaxFn.

那么現(xiàn)在,我們的目的是使displayUsers這個(gè)函數(shù)在不傳參數(shù)的情況下照樣工作,即,運(yùn)行displayUsers()要得到和上面一樣的結(jié)果,如果我們直接運(yùn)行,你會(huì)發(fā)現(xiàn)報(bào)錯(cuò)了:

Uncaught TypeError: Cannot read property "get" of undefined

很明顯是因?yàn)閍jax這個(gè)參數(shù)沒(méi)有定義。

來(lái)實(shí)現(xiàn)依賴(lài)注入

現(xiàn)在大部分的框架都提供依賴(lài)注入機(jī)制的模塊,可能會(huì)叫做:injector。為了在某個(gè)地方使用一個(gè)依賴(lài),我們需要在那個(gè)地方注冊(cè)那個(gè)依賴(lài):

來(lái)創(chuàng)建我們的injector

var injector = {
  storage: {},
  register: function(name, resource) {
    this.storage[name] = resource;
  },
  resolve: function(target) {

  }
};

我們只需要兩個(gè)方法,第一個(gè)是register, 接收我們的依賴(lài)并將它存儲(chǔ)起來(lái)。第二個(gè)方法是resolve,這個(gè)方法接收的參數(shù)是我們我們要注入依賴(lài)的對(duì)象,這里的關(guān)鍵的點(diǎn)就是這個(gè)注入器不應(yīng)該調(diào)用我們的函數(shù),所以我們?cè)趓esolve方法中返回一個(gè)閉包來(lái)包裹我們的target,然后再調(diào)用它:

resolve: function(target) {
  return function() {
    target();
  };
}

那么到現(xiàn)在呢,我們的注入器依然是不可用的:

displayUsers = injector.resolve(displayUsers);
displayUsers();

我們依然得到同樣的錯(cuò)誤,你覺(jué)得少了什么呢?絕壁就是依賴(lài)項(xiàng)了,所以我們下一步就是要找出這個(gè)函數(shù)的依賴(lài)項(xiàng),如何找? 這是比較棘手的問(wèn)題,不過(guò)我們可以參考angularjs的方式:

var FN_ARGS = /^functions*[^(]*(s*([^)]*))/m;
var STRIP_COMMENTS = /((//.*$)|(/*[sS]*?*/))/mg;
...
function annotate(fn) {
  ...
  fnText = fn.toString().replace(STRIP_COMMENTS, "");
  argDecl = fnText.match(FN_ARGS);
  ...
}
We purpo

這里省略了一些細(xì)節(jié)部分,我們需要注意的就是annotate這個(gè)函數(shù),它負(fù)責(zé)將目標(biāo)函數(shù)轉(zhuǎn)換為一個(gè)字符串,刪除它的注釋(如果有),然后提取他的參數(shù)(依賴(lài)項(xiàng)):

resolve: function(target) {
  var FN_ARGS = /^functions*[^(]*(s*([^)]*))/m;
  var STRIP_COMMENTS = /((//.*$)|(/*[sS]*?*/))/mg;
  fnText = target.toString().replace(STRIP_COMMENTS, "");
  argDecl = fnText.match(FN_ARGS);
  console.log(argDecl);
  return function() {
    target();
  }
}

上面主要是通過(guò)正則表達(dá)式來(lái)找到依賴(lài)項(xiàng),來(lái)看看結(jié)果:

你會(huì)看到返回的數(shù)組中包含了我們需要的依賴(lài)項(xiàng),我們找到它們并用注入器注冊(cè)和存儲(chǔ):

resolve: function(target) {
  var FN_ARGS = /^functions*[^(]*(s*([^)]*))/m;
  var STRIP_COMMENTS = /((//.*$)|(/*[sS]*?*/))/mg;
  fnText = target.toString().replace(STRIP_COMMENTS, "");
  argDecl = fnText.match(FN_ARGS)[1].split(/, ?/g);
  var args = [];
  for(var i=0; i

現(xiàn)在,我們可以使用我們的注入器了:

injector.register("domEl", body);
injector.register("ajax", ajaxFn);

displayUsers = injector.resolve(displayUsers);
displayUsers();

你會(huì)發(fā)現(xiàn)得到了和剛開(kāi)始一樣的結(jié)果。

這樣做有什么優(yōu)點(diǎn)呢?有點(diǎn)就是我們可以把DOM元素和ajaxFn注入到任何一個(gè)函數(shù)中,我們甚至可以將我們的應(yīng)用程序配置成這樣的方式,那我們就不用通過(guò)繼承來(lái)傳遞這些對(duì)象了。這僅僅是injector的register和resolve方法而已,我們的注入器還不夠完美,還有擴(kuò)展空間,比如定義作用域scope.

而angularjs中的依賴(lài)注入更加強(qiáng)大:

displayUsers = injector.resolve(["domEl", "ajax", displayUsers]);

和displayUsers 不同,它傳遞的是真實(shí)的依賴(lài)名稱(chēng)。

譯自:http://www.sitepoint.com/revealing-magic-javascript/

有錯(cuò)誤還請(qǐng)指正!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/85840.html

相關(guān)文章

  • AngularJs 入門(mén)(一)--前言

    摘要:入門(mén)一前言目前來(lái)說(shuō)相對(duì)于現(xiàn)在流行的高版本以及來(lái)說(shuō)實(shí)屬是老套的前端框架了,當(dāng)然這都不重要,沒(méi)有完美的框架,只有不斷優(yōu)化的代碼。通過(guò)使用我們稱(chēng)為指令的結(jié)構(gòu),讓瀏覽器能夠識(shí)別新的語(yǔ)法。使用作為輸入,而不是字符串,是區(qū)別于其它的框架的最大原因。 AngularJs 入門(mén)(一) 前言 AngularJs目前來(lái)說(shuō)相對(duì)于現(xiàn)在流行的高版本ng2、ng4,以及Vue2.0、React來(lái)說(shuō)實(shí)屬是老套的前...

    wenyiweb 評(píng)論0 收藏0
  • 【譯】《精通使用AngularJS開(kāi)發(fā)Web App》(五)

    摘要:上一篇譯精通使用開(kāi)發(fā)四下一篇譯精通使用開(kāi)發(fā)六書(shū)名合作對(duì)象正如所見(jiàn),提供了一種將對(duì)象組織為模塊的方式。模塊不僅可以注冊(cè)可以直接被框架所調(diào)用的對(duì)象控制器,過(guò)濾器等,還可以使用任何應(yīng)用開(kāi)發(fā)者所定義的對(duì)象。 上一篇:【譯】《精通使用AngularJS開(kāi)發(fā)Web App》(四) 下一篇:【譯】《精通使用AngularJS開(kāi)發(fā)Web App》(六) 書(shū)名:Mastering Web Applic...

    PiscesYE 評(píng)論0 收藏0
  • AngularJS 依賴(lài)注入

    摘要:代碼代碼需要注意的地方這個(gè)方法只適合未經(jīng)過(guò)壓縮和混淆的代碼因?yàn)樾枰嘉唇?jīng)壓縮的參數(shù)列表來(lái)進(jìn)行解析。代碼代碼注意的地方行內(nèi)聲明的方式允許我們直接傳入一個(gè)參數(shù)數(shù)組而不是一個(gè)函數(shù)。 AngularJS 依賴(lài)注入的方法 1. 通過(guò)函數(shù)的參數(shù)進(jìn)行推斷式注入聲明 如果沒(méi)有明確的什么, AngularJS 會(huì)假定參數(shù)名稱(chēng)就是依賴(lài)的名稱(chēng)。因此, 它會(huì)在內(nèi)部調(diào)用函數(shù)對(duì)象的 toString() 方法...

    mindwind 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<