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 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个例子,很生动有助于理解。看完博主的文章,结合之前的开发经验有一种顿悟的感觉。

四、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 
    该服务监听指定类型的事件,获取从emit或者broadcast发布的事件。 
    【提示】:

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

时间: 2024-11-05 20:45:14

angular问题总结的相关文章

angular中模板

<!DOCTYPE html><!--调用模块--><html lang="en" ng-app="myApp"><head> <meta charset="UTF-8"> <script src="js/angular.js"></script> <title>Title</title></head><

利用angular打造管理系统页面

1 创建一个新的angular应用 ng new adminSystem 2 利用WebStorm打开adminSystem应用 3 借助AdminLTE这个开源项目来辅助开发 AdminLTE项目:点击前往 将AdminLTE项目的精简版本源代码复制到adminSystem应用主模块的主组件的模板中 AdminLTE项目的精简版本效果图 <!DOCTYPE html> <!-- This is a starter template page. Use this page to star

Angular基础(二) 组件的使用

? 一.简单操作 a) 使用Angular CLI可以快速创建项目框架,先运行 $ npm install –g @angular/[email protected]安装CLI,为CLI的位置设置环境变量,然后就可以全局使用ng命令了. 执行ng new –ng4 angular-hello-world可以创建Angular4项目,会自动生成基础的文件夹和文件,还会自动进行npm i操作,下载并安装所需的依赖. 然后执行ng serve就可以编译并启动这个程序了,但ng并不会自动打开浏览器. b

Angular 2基础(一) 环境搭建

Angular2是一款开源JavaScript库,由Google维护,用来创建页面应用程序.正式发布于2016年9月,基于ES6开发. 一.准备工作 使用Angular2开发,需要预先做一些配置上的配置,如NPM.Node.Js.Git等,还要对TypeScript有个大概的了解. a)NPM是随同NodeJS一起安装的包管理器,那应该类似NuGet的作用了.NPM集成在了NodeJS安装包,可以一起安装,在CMD输入npm –v和node –v可以验证是否已安装. b)TypeScript则是

angular踩坑之路:初探webpack

之前费了一番力气安装好了angular开发环境,后面的几天都是在angular中文官网上看文档,照着英雄教程一步一步操作,熟悉了angular的一些基本特性,这部分没有遇到什么大问题,还比较顺利.这两天在看官方文档中的Webpack简介,想跟着文档做一遍,了解一下如何用Webpack打包angular项目,结果遇到了一些问题,因为是初学angular和Webpack的小白,这些问题一时难以解决,花费了不少时间,想在这里记录一下. 首先跟着文档将相关的文件都添加到项目中,目录是这样子的: 根据文档

angular参考手册拷贝

AngularJS 参考手册 AngularJS 指令 本教程用到的 AngularJS 指令 : 指令 描述 ng-app 定义应用程序的根元素. ng-bind 绑定 HTML 元素到应用程序数据 ng-bind-html 绑定 HTML 元素的 innerHTML 到应用程序数据,并移除 HTML 字符串中危险字符 ng-bind-template 规定要使用模板替换的文本内容 ng-blur 规定 blur 事件的行为 ng-change 规定在内容改变时要执行的表达式 ng-check

angular 动画

ngAnimate 做了什么? ngAnimate 模型可以添加或移除 class . ngAnimate 模型并不能使 HTML 元素产生动画,但是 ngAnimate 会监测事件,类似隐藏显示 HTML 元素 ,如果事件发生 ngAnimate 就会使用预定义的 class 来设置 HTML 元素的动画. AngularJS 添加/移除 class 的指令: ng-show ng-hide ng-class ng-view ng-include ng-repeat ng-if ng-swit

angular.copy和angular.extend

angular.copy用于深复制,而angular.extend用于拓展.     angular.copy(src,[dst]) src:源对象 dst:目标对象,复制的对象 js中 '= '操作符复制的是指针,所以前后两个变量指向的还是内存中的同一个对象,所以在其中一个变量上操作该对象时,对另外一个变量也会生效.而angular.copy方法是深复制,会在内存中再生成一个对象,两个变量彼此独立,互不影响. 接收一个必须参数src,一个可选参数dst.如果dst没有提供,就会创建对象或者数组

.Net Core + Angular Cli 开发环境搭建

一.基础环境配置 1.安装VS 2017 v15.3或以上版本 2.安装VS Code最新版本 3.安装Node.js v6.9以上版本 4.重置全局npm源,修正为 淘宝的 NPM 镜像: npm install -g cnpm --registry=https://registry.npm.taobao.org 5.安装TypeScript cnpm install -g typescript typings 6.安装 AngularJS CLI cnpm install -g @angul

Angular this vs $scope

this vs $scope ------------------------------------------------------------------------------ 'this' vs $scope in AngularJS controllers How does this and $scope work in AngularJS controllers? Short answer: this When the controller constructor functio