實踐總結 - 不可錯過的Angular應用技巧

angular的核心思想是經過數據驅動一切,其餘東西都是數據的延伸.

套用Javascript一切皆對象的思想,在angular中能夠說一切皆數據. 
html

  關於項目構建
html5

    

    (1) requirejs以及Yeomanjquery

    在剛開始接觸或者使用Angular的時候,總會疑惑與相似的問題,我實踐的答案是不須要requirejs或者Yeoman.前者不使用,由於angular自己有module的實現.後者是由於Angular組織結構以及項目構建徹底沒必要要弄得如此繁雜,手寫或者在github上pull一個seed項目便可.
git


    (2) 如何組織項目結構
github

    這個問題有點廢材,由於徹底因人因項目而異.我的推薦的是兩種組織結構,一種按照代碼功能,也就是controller都放在一個文件夾下,services都放在一個文件夾下.另外一種則遵循所實現的功能,好比User就把對應的template,services,controller都放在User文件夾下.
web

    兩種均可以,從維護角度上看第二種會更好一些.express


    (3) controller以及service的劃分
flask

    這裏controller一般就是一個頁面一個controller,假如一個頁面有公共的部分,公共部分永遠使用一個controller.對於service要劃分紅兩個部分,一個是於服務器交互數據的service,另外一個是一些功能性common的內容,其中放置一些本身寫的可複用的服務,相似於notify等.
後端

    至於service要不要按照功能和模塊再進一步劃分,這個就看項目來了.
promise


    (4) Angular插件以及庫的使用

    對於一個項目全部的東西都去網上拿現成的確定不現實,可是全部的東西都本身寫就更不實際了.Angular的不少插件是由Angular團隊開發出來或者一些人用jquery插件封裝的.我對於插件的觀點很簡單,若是拿來用趕忙需求能夠知足就用,不能知足就本身寫或者在已有插件上改進.

    對於若是你調試幾個小時還搞不定的插件,聽個人勸,放棄它吧.大多數插件都是一些UI插件,大可沒必要追求繁雜,有時候簡簡單單的HTML控件也自有它簡約的美.

    若是你遇到Angular插件衝突,尤爲是UI插件,大多數的狀況下要放棄其中之一,好比angular-ui和angular-strap.

    

  使用技巧


    下面進入正文,我會列舉出我在使用angular的過程當中使用的一些技巧,會以場景的形式一一列舉.這裏對於Angular的一些基礎概念我不會解釋,本文是一些技巧性的東西,不是基礎教程.


    (1) angular中"{{}}"於Python的flask衝突

    Python的flask使用的模板中,數據綁定也是經過兩個"{"大括號,這就於angular的數據綁定有衝突.這個有兩種解決方法,一種是修改angular的綁定標記,另外一種就是修改flask的綁定標記,這裏兩種方案都給出.

    修改angular:

$interpolateProvider.startSymbol('{[{').endSymbol('}]}');
// 將這句話加在config中便可,放在route的module中便可.這裏將原來angular的{{ }}綁定,修改成經過{[{ }]}綁定.

    

    修改flask:

class CustomFlask(Flask):
    jinja_options = Flask.jinja_options.copy()
    jinja_options.update(dict(
        block_start_string='{%',
        block_end_string='%}',
        variable_start_string='{#',
        variable_end_string='#}',
        comment_start_string='<#',
        comment_end_string='#>',
    ))
    
app = CustomFlask(__name__, instance_path='/web')

    這裏我推薦修改flask,由於用了angular以後,先後端分離.flask的jinjia模板再也不須要,同時若是你修改了Angular的綁定標記,其餘的控件和庫會有問題的.


    (2) 去除url中老是默認帶有"#"

    在設置route的時候,開啓HTML5模式.

angular.module('router', ['ngRoute'])
.config(['$routeProvider', '$locationProvider',
  function($routeProvider, $locationProvider) {
    $locationProvider.html5Mode(true);   // 設置一下這句便可
  }
]);

    

    (3) ng-click="expression"以及相似的指令,如何在expression中書寫多個表達式?

    好比我在一個ng-click中想要給2個變量賦值,經過";"分號分割便可:

<a ng-click="obja=1;objb=2"></a>


    (4) $watch沒有產生做用或者只生效一次

    這種狀況通常來講是監聽一個字符串或者數字的時候會出現,$scope.$watch("name",function(){}).沒有生效或者只生效一次,解決方法是$watch儘可能監聽的是一個對象,將你要監聽的值附在一個Object下便可.

    當你使用angular-ui中的modal時,這個比較明顯.具體的緣由是由於$scope的繼承,由於modal至關於在當前頁面的controller中又建立了一個scope,因此對於字面量無法檢索追溯原型鏈,想解決就要有一個對象,才能經過原型鏈實現跨父子scope的數據刷新綁定.


    (5) 但願ng-view的內容全頁面顯示

    一般一個頁面可能會有固定的top-menu或者sidebar,這類固定不變的部分,而後每次route變化的都是ng-view的template,若是一個頁面但願整個頁面徹底顯示它本身,不包括top-menu之類固定的部分.

    這裏一般是一個index.html和一個ng-view顯示的template.html,top-menu和sidebar位於index.html中,將它們的顯示隱藏經過ng-if綁定一個變量控制.

    若是一個頁面須要本身徹底顯示,不顯示sidebar等,則在其controller中經過$scope.$emit向上發送一個消息,而後index頁面的controller則經過$scope.$on監聽消息,一旦聽到那個消息,則改變控制sidebar顯隱的變量.

    也能夠經過service作一個全局的變量控制,我的推薦仍是經過消息廣播的方式.


    (6) 切記用ng-if代替ng-show

    這是angular的一個小坑,也能夠說是不大不小的一個坑.一些長列表數據,可能有一些東西是經過默認隱藏,點擊顯示的形式展示的.而這部分可控制顯隱的內容中也會伴隨不少數據綁定.這個在頁面渲染的時候很是影響性能.

    舉一個列子,好比說一般angular建議一個頁面的數據綁定不超過2000個,假如如今有一個頁面直接綁定了2000個model,而後你加載,會發現很是卡.若是你將每100的model設置爲ng-show,默認狀況下不顯示,你會發現仍是很卡.

    而後你將全部的ng-show換成ng-if,你會發現性能瞬間快的像兩個應用.緣由在ng-show仍是會執行其中的全部綁定,ng-if則會在等於true,也就是顯示的時候再去執行其中的綁定.這樣一來性能就有很大的提升,我以前經過這個簡單的修改,頁面加載快了10倍左右.

    因此在能使用ng-if的狀況,用它代替全部的ng-show和ng-hide吧.

    

    (7) 關於ng-bind-html

    一般狀況下爲html元素綁定數據,有ng-bind就夠了,但一些情境下須要綁定的不是通常的數據,而是html.那麼ng-bind就不夠用了,須要使用ng-bind-html,它會將內容做爲html格式輸出.好比想輸出帶有class的html,那麼就使用ng-bind-html,並且還須要ngSanitize的配合,須要引入相應的文件.


    (8) 獲取ng-repeat數據filter後的結果

    這個通常在搜索的時候須要用到,好比多重ng-repeat數據造成列表.而後filter一個字段,如今要獲得filter以後的結果,有2中方式.

    一種是在html的ng-repeat中相似這麼寫:

ng-repeat="food in foodCategory._displayfoods = (foodCategory.foods | filter: { 'name': searchobj.foodfilter } | orderBy: food.sort_order)"

    這樣_displayfoods就是filter後的最終顯示的結果.另外一種方式是經過兩套數據,一套寫在controller中,而後filter以及orderBy都是在controller中操做,最後操做的結果在用來ng-repeat.

    第一種方式比較方便,第二種方式更好,性能也好.


    (9) ng-class以及ng-style經過判斷賦值

    根據變量的值決定是否應用某種class,以及不一樣的style樣式.

    ng-class="{'state-error':!foodForm.foodstock.$valid}"

    ng-style="{ color: i.color=='' || i.name=='活' ? 'default' : '#fff' }"


    (10) form校驗以input爲例

    angular的form能夠經過input的HTML5屬性進行校驗,這裏主要經過form以及input的name屬性進行鎖定,formname.inputname.$valid表示name爲inputname的空間是否經過自己的屬性校驗.


    (11) $resource和$http的$promise

$q.all([
  resource.query().$promise,
  resource2.query().$promise
]).then(functon(success){
  console.log(success);
},functon(error){
  console.log(error);
});

foodFactory.food.save(f).$promise.then(function(result){
  foodFactory.food.get({id:result.id}).$promise.then(function(data){
  });
});

    這個不解釋了,直接看就能夠了,注意$http的promise須要手動返回,因此通常狀況下都經過$resource.


    (12) 僅$watch監聽collection中的一個屬性

    $watch的第三個參數設置爲true,便可deep watch.不過有時候其實不想或者不須要監聽collection的所有屬性.只要監視其中的一個或者幾個,這時候經過for循環雖然能夠循環$watch不過明顯太挫.

    經過下面這種寫法就能夠監控一個collection的單獨一個object屬性.

$scope.people = [
    {
        "groupname": "g1", 
        "persions": [
            {
                "id": 1, 
                "name": "bill"
            }, 
            {
                "id": 2, 
                "name": "bill2"
            }
        ]
    }, 
    {
        "groupname": "g2", 
        "persions": [
            {
                "id": 3, 
                "name": "bill3"
            }, 
            {
                "id": 4, 
                "name": "bill4"
            }
        ]
    }
]

$scope.$watch(function($scope) {
    return $scope.people.map(function(obj) {
        return obj.persions.map(function(g){
            return g.name
        });
    });
}, function (newVal) {
    $scope.count++;
    $scope.msg = 'person name was changed'+ $scope.count;
}, true);

    

    (13) debounce防抖處理

    這個對於頻繁出發的處理很是有用,適用於相似ng-change,$watch的一些場景.好比根絕關鍵字即時搜索的場合,將$debounce封裝爲服務,直接調用接口,代碼:http://jsfiddle.net/Warspawn/6K7Kd/


    (14) 快速定位到某個位置

    通常來說頁面內經過<a id="bottom"></a>這樣的形式就能夠結合js代碼,實現快速定位.在angular中也是經過相似的原理實現,代碼以下:

          var old = $location.hash();
          $location.hash('batchmenu-bottom');
          $anchorScroll();
          $location.hash(old);

    這樣寫是由於直接location.hash會致使url變化,頁面跳轉,因此加了防止跳轉的代碼.

    暫時就總結了這麼多,不少東西都是查資料以及本身實踐的,但願對須要的TX會有所幫助,之後若是有新的東西會續寫一下.

相關文章
相關標籤/搜索