实践总结 - 不可错过的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会有所帮助,之后若是有新的东西会续写一下.

相关文章
相关标签/搜索