angular问题总结

摘要:
自Angular开发以来,已有大约三个月的时间。前两周非常艰难,我逐渐熟悉了。

已经用angular开发了大概有三个月了,开始两周很艰难,慢慢的也渐渐熟悉一些了。在此整理一下这段时间遇到的各种坑。

一、Angular怎样停止请求

(1)首先在需要请求的controller中注入$q服务,

(2)在scope变量中声明一个变量,var canceler;

(3)在事件最上方写上

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

(4)在请求的位置添加一个延时

$http.jsonp(drivingUrl,{
    timeout:canceler.promise 
}).success(response);
 二、ng-repeat的渲染问题

业务中有时需要在异步获取数据并用ng-repeat遍历渲染完页面后执行某个操作,angular本身并没有提供监听ng-repeat渲染完成的指令,所以需要自己动手写。在ng-repeat模板实例内部会暴露出一些特殊属性$index/$first/$middle/$last/$odd/$even,$index会随着每次遍历(从0开始)递增,当遍历到最后一个时,$last的值为true,所以通过判断$last的值来监听ng-repeat的执行状态,可以自定义指令

//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

 三、Directive指令中的scope(摘自https://segmentfault.com/a/1190000002773689)

AngularJS为我们指令的scope参数提供了三种选择,分别是:false,true,{};默认情况下是false

1.scope = false

我们就新创建了一个作用域,只不过这个作用域是继承了我们的父作用域;我觉得可以这样理解,我们新创建的作用域是一个新的作用域,只不过在初始化的时候,用了父作用域的属性和方法去填充我们这个新的作用域。它和父作用域不是同一个作用域。

2.scope = true

我们创建的指令和父作用域(其实是同一个作用域)共享同一个model模型,所以在指令中修改模型数据,它会反映到父作用域的模型中。

3.scope = {}

当我们将scope设置为{}时,意味着我们创建的一个新的与父作用域隔离的新的作用域,这使我们在不知道外部环境的情况下,就可以正常工作,不依赖外部环境。

 

我们使用了隔离的作用域,不代表我们不可以使用父作用域的属性和方法。

 

  1. 我们可以通过向scope{}中传入特殊的前缀标识符(即prefix),来进行数据的绑定。
  2. 在创建了隔离的作用域,我们可以通过@,&,=引用应用指令的元素的属性,如上面的代码那样,我们可以在<div 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个例子,很生动有助于理解。看完博主的文章,结合之前的开发经验有一种顿悟的感觉。

四、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;

}); 

五、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。

六、控制器之间的通信

angularjs中提供了emit,broadcast和$on服务用于控制器之间基础事件的传递交流。 

  1. $emit 
    该服务贯穿作用域发出一个向上的事件,并通知哪些注册在rootScope.Scope的监听器。该事件的生命周期开始于emit被启动的地方,事件一直朝着根作用域传递,传递期间并通知哪些注册在作用域上的监听器,如果这期间一个监听器接受到了这个事件,会注销这个事件,那么事件将会停止向上继续传播。 
  2. $broadcast 
    该服务发布一个向下的事件给作用域中的所有子节点以及以下的节点,并通知注册在 
    rootScope.Scope的监听器,该事件的生命周期也是从broadcast被启动开始。下面的所有作用域都会接收到通知。之后,事件向下传播,在这期间,作用域中的监听器接收到通知,获取事件,但是不会注销事件,事件继续往下传播。
  3. $on 
    该服务监听指定类型的事件,获取从emitbroadcast发布的事件。 
    提示:

如果在作用域中没有父子关系存在,可以在控制器中注入$rootScope、使用$broadcast服务向下传播事件,但是不能通过$emit向上传播事件。在作用域中存在父子关系时,可以也仅可以由子控制器使用$emit服务向上传播事件,同时父作用域中的控制监听器可以注销事件。

 

免责声明:文章转载自《angular问题总结》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇PHP CLI模式开发MySQL 半同步复制+MMM架构下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Android监听

流程模型图: 文字表述: 事件监听机制中由事件源,事件,事件监听器三类对象组成 处理流程如下: Step 1:为某个事件源(组件)设置一个监听器,用于监听用户操作 Step 2:用户的操作,触发了事件源的监听器 Step 3:生成了对应的事件对象 Step 4:将这个事件源对象作为参数传给事件监听器 step 5:事件监听器对事件对象进行判断,执行对应的...

XD 05

项目启动方式 1. 在 springBoot application 上右键 run as Java application 2. run as mvn install 会打包一个jar 包 3. war 在 tomcat, war 包方式, 一般 springBoot 都是使用 jar 包启动了 a. 首先在 pom 文件中添加 <packagin...

jmeter之如何减负-实现稳定超高并发测试(性能调优)之正确添加监听器

jmeter之如何减负-实现稳定超高并发测试(性能调优)在测试过程中,初学者使用工具不当,添加众多监控组件,非常想看到实时报告,跑不了一会,jmeter就卡死,只得重启 下面来总结下如何正确使用jmeter,有效利用执行资源,小型机器也可以实现高并发负载。 减负一: 优化监听(GUI模式)“查看结果树”,需要勾选“仅日志错误”,这样只会保存错误日志到内存,...

12 jmeter性能测试实战--web程序

项目背景 项目:XX网站环境:Windows需求:并发登录的性能测试场景:1s增加2个线程,运行2000次(线程数20,Ramp-Up seconds 10,循环次数100)。分别看20、40、60并发下的表现监控:成功率、响应时间、标准差、CPU、mem、io等。资源监控需要在Windows下部署监控agent(serveragent) 测试步骤 1.W...

CentOS 5下freeswitch中集成使用ekho实现TTS功能二

三:以上Festival安装完成以后回到ekho安装目录: 执行./configure --enable-festival 前 更改configure 1:替换 #AC_DEFINE(ENABLE_FESTIVAL,,[Enable Festival]) #LIB_FESTIVAL="${srcdir}/lib/libFestival.a ${srcdir...

angularjs中的事件传播$emit,$broadcast,$on

在这里写的技术点 一部分参考AngularJs权威教程一部分参考的是其它的博主的知识点 事件 :如同浏览器响应浏览器层的事件,比如鼠标点击、页面滚动那样,Angular应用也可以响应Angular事件.这使我们在我们应用中嵌套各组件之间进行通信,即使这些组件在创建的时候并未考虑其他组件.我们可以认为事件是在应用中传播的事件信息片段,通常包含应用中发生的事件...