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服务向上传播事件,同时父做用域中的控制监听器能够注销事件。

相关文章
相关标签/搜索