angular問題總結

已經用angular開發了大概有三個月了,開始兩週很艱難,慢慢的也漸漸熟悉一些了。在此整理一下這段時間遇到的各類坑。angularjs

1、Angular怎樣中止請求

(1)首先在須要請求的controller中注入$q服務,json

(2)在scope變量中聲明一個變量,var canceler;segmentfault

(3)在事件最上方寫上數組

//取消以前的請求
if (canceler) canceler.resolve();
canceler = $q.defer();

(4)在請求的位置添加一個延時promise

$http.jsonp(drivingUrl,{
    timeout:canceler.promise 
}).success(response);

 2、ng-repeat的渲染問題

業務中有時須要在異步獲取數據並用ng-repeat遍歷渲染完頁面後執行某個操做,angular自己並無提供監聽ng-repeat渲染完成的指令,因此須要本身動手寫。在ng-repeat模板實例內部會暴露出一些特殊屬性$index/$first/$middle/$last/$odd/$even,$index會隨着每次遍歷(從0開始)遞增,當遍歷到最後一個時,$last的值爲true,因此經過判斷$last的值來監聽ng-repeat的執行狀態,能夠自定義指令app

//ng-repeat-finish //解決ng-repeat時間有一個渲染時間,加載延遲問題
routerApp.directive("ngRepeatFinish", function() {
    return {
        restrict: "A",
        scope: {},        
        link: function($scope, element, attr){
            if($scope.$parent.$last){
                //要處理的函數
            }
        }
    }

});

參考博客http://www.tuicool.com/articles/Fb2um2e異步

 3、Directive指令中的scope(摘自http://www.javashuo.com/article/p-almsioew-ew.html)

AngularJS爲咱們指令的scope參數提供了三種選擇,分別是:false,true,{};默認狀況下是falseide

1.scope = false

咱們就新建立了一個做用域,只不過這個做用域是繼承了咱們的父做用域;我以爲能夠這樣理解,咱們新建立的做用域是一個新的做用域,只不過在初始化的時候,用了父做用域的屬性和方法去填充咱們這個新的做用域。它和父做用域不是同一個做用域。函數

2.scope = true

咱們建立的指令和父做用域(實際上是同一個做用域)共享同一個model模型,因此在指令中修改模型數據,它會反映到父做用域的模型中。jsonp

3.scope = {}

當咱們將scope設置爲{}時,意味着咱們建立的一個新的與父做用域隔離的新的做用域,這使咱們在不知道外部環境的狀況下,就能夠正常工做,不依賴外部環境。

 

咱們使用了隔離的做用域,不表明咱們不可使用父做用域的屬性和方法。

 

  1. 咱們能夠經過向scope{}中傳入特殊的前綴標識符(即prefix),來進行數據的綁定。
  2. 在建立了隔離的做用域,咱們能夠經過@,&,=引用應用指令的元素的屬性,如上面的代碼那樣,咱們能夠在<div class="my-directive" my-directive my-name="{{name}}" age="age" change-my-age="changeAge()"></div>這個元素中,利用前綴標識符經過使用屬性my-name,age,change-my-age來引用這些屬性的值。

 

下面咱們來看看如何使用這些前綴標識符:

 

@

 

這是一個單項綁定的前綴標識符
使用方法:在元素中使用屬性,比如這樣<div my-directive my-name="{{name}}"></div>,注意,屬性的名字要用-將兩個單詞鏈接,由於是數據的單項綁定因此要經過使用{{}}來綁定數據。

 

=

 

這是一個雙向數據綁定前綴標識符
使用方法:在元素中使用屬性,比如這樣<div my-directive age="age"></div>,注意,數據的雙向綁定要經過=前綴標識符實現,因此不可使用{{}}

 

&

 

這是一個綁定函數方法的前綴標識符
使用方法:在元素中使用屬性,比如這樣<div my-directive change-my-age="changeAge()"></div>,注意,屬性的名字要用-將多個個單詞鏈接。

 

注意:在新建立指令的做用域對象中,使用屬性的名字進行綁定時,要使用駝峯命名標準,好比下面的代碼。

 

進一步說明,咱們的指令是如何利用這些前綴標識符來尋找咱們想要的屬性或者函數的?

 

  • @ 當指令編譯到模板的name時,就會到scope中尋找是否含有name的鍵值對,若是存在,就像上面那樣,看到@就知道這是一個單向的數據綁定,而後尋找原來的那個使用指令的元素上(或者是指令元素自己)含有這個值的屬性即my-name={{name}},而後在父做用域查找{{name}}的值,獲得以後傳遞給模板中的name
  • =&@差很少,只不過=進行的是雙向的數據綁定,不論模板仍是父做用域上的屬性的值發生改變都會使另外一個值發生改變,而&是綁定函數而已。

原博主微博還有3個例子,很生動有助於理解。看完博主的文章,結合以前的開發經驗有一種頓悟的感受。

4、Filter

Angular自帶的內置 filter有九種:

1) date(日期)

2) currency(貨幣)

3) limitTo(限制數組或字符串長度)

4) orderBy(排序)

5) lowercase(小寫)

6) uppercase(大寫)

7) number(格式化數字,加上千位分隔符,並接收參數限定小數點位數)

8) filter(處理一個數組,過濾出含有某個子串的元素)

9) json(格式化 json 對象)

1.filter 有兩種使用方法,一種是直接在頁面裏:

<p>{{now | date : 'yyyy-MM-dd'}}</p>

2.另外一種是在 js 裏面用:

// $filter('過濾器名稱')(須要過濾的對象, 參數1, 參數2,...)

$filter('date')(now, 'yyyy-MM-dd hh:mm:ss');

自定義 filter

// 形式

app.filter('過濾器名稱',function(){

    return function(須要過濾的對象,過濾器參數1,過濾器參數2,...){

        //...作一些事情  

        return 處理後的對象;

    }

});  

// 一個高亮的例子

routerApp.filter("highlight", function($sce, $log){

var fn = function(text, search){

    if (!search) {

        return $sce.trustAsHtml(text);

    }

    var regex = new RegExp(search, 'gi');

    var result = text;   

    try{

     result = text.replace(regex, '<span class="highlightedText red">$&</span>');

}catch(e){

// 輸入了特殊字符

}

    return $sce.trustAsHtml(result);

};

return fn;

}); 

5、factory、service 和 provider 關係

factory

service 的方法和數據放在一個對象裏,並返回這個對象

app.factory('FooService', function(){

    return {

        target: 'factory',

        sayHello: function(){

            return 'hello ' + this.target;

        }

    }

}); 
service

經過構造函數方式建立 service,返回一個實例化對象

app.service('FooService', function(){

    var self = this;

    this.target = 'service';

    this.sayHello = function(){

        return 'hello ' + self.target;

    }

});
provider

建立一個可經過 config 配置的 service,$get 中返回的,就是用 factory 建立 service 的內容

app.provider('FooService', function(){

    this.configData = 'init data';

    this.setConfigData = function(data){

        if(data){

            this.configData = data;

        }

    }

    this.$get = function(){

        var self = this;

        return {

            target: 'provider',

            sayHello: function(){

                return self.configData + ' hello ' + this.target;

            }

        }

    }

});

// 此處注入的是 FooService 的 provider

 
 

app.config(function(FooServiceProvider){

 
 

    FooServiceProvider.setConfigData('config data');

 
 

});

從底層實現上來看,service 調用了 factory,返回其實例;factory 調用了 provider,返回其 $get 中定義的內容。factory 和 service 功能相似,只不過 factory 是普通 function,能夠返回任何東西(return 的均可以被訪問,因此那些私有變量怎麼寫,你懂的);service 是構造器,能夠不返回(綁定到 this 的均可以被訪問);provider 是增強版 factory,返回一個可配置的 factory。

6、控制器之間的通訊

angularjs中提供了emit,broadcast和$on服務用於控制器之間基礎事件的傳遞交流。 

  1. $emit 
    該服務貫穿做用域發出一個向上的事件,並通知哪些註冊在rootScope.Scope的監聽器。該事件的生命週期開始於emit被啓動的地方,事件一直朝着根做用域傳遞,傳遞期間並通知哪些註冊在做用域上的監聽器,若是這期間一個監聽器接受到了這個事件,會註銷這個事件,那麼事件將會中止向上繼續傳播。 
  2. $broadcast 
    該服務發佈一個向下的事件給做用域中的全部子節點以及如下的節點,並通知註冊在 
    rootScope.Scope的監聽器,該事件的生命週期也是從broadcast被啓動開始。下面的全部做用域都會接收到通知。以後,事件向下傳播,在這期間,做用域中的監聽器接收到通知,獲取事件,可是不會註銷事件,事件繼續往下傳播。
  3. $on 
    該服務監聽指定類型的事件,獲取從emitbroadcast發佈的事件。 
    提示:

若是在做用域中沒有父子關係存在,能夠在控制器中注入$rootScope、使用$broadcast服務向下傳播事件,可是不能經過$emit向上傳播事件。在做用域中存在父子關係時,能夠也僅能夠由子控制器使用$emit服務向上傳播事件,同時父做用域中的控制監聽器能夠註銷事件。

相關文章
相關標籤/搜索