AngularJS 1.X 重点知识详解一

$scope

    作用域(scope)是构成AngularJS的核心基础,$scope对象是定义应用业务逻辑、控制器方法和视图属性的地方。作用域是视图和控制器之间的胶水,在应用将视图渲染并呈现给用户之前,视图中的模板会和作用域进行连接,然后应用会将对DOM的设置以便将属性变化通知给AngularJS. $scope主要有3个方面的特点:1.通过数据共享连接controller和view;2. 事件的监听和响应; 3. 脏数据检查和数据绑定;

    $scope的生命周期

            $scope对象的生命周期处理有4个不同的阶段,创建-链接-更新-销毁

            创建

                在创建控制器或指令时,AngularJS会用$injector创建一个新的作用域,并在这个新建的控制器或指令运行时将作用域传递出去。

            链接

                当AngularJS开始运行时,所有的$scope对象都会附加或链接到视图中。所有创建$scope对象的函数也会自身附加到视图中,这些作用域将会注册当AngularJS应用上下文中发生变化时,需要运行的函数。这些函数被称为$watch函数,AngularJS通过这些函数获知何时启动事件循环。

            更新

                当事件循环运行时,它通常执行在顶层的$scope对象上($rootScope),每个子作用域都执行自己的脏值检测。每个监控函数都会检查变化。如果检查到任意变化,$scope 就会触发指定的回调函数。

            销毁

                 当一个$scope在视图中不再需要的时候,这个作用域将会清理和销毁自己。在$scope对象上调用$destory()方法来清理这个作用域。

            AngularJS 1.2 引入了一个叫controller as syntax 的概念。它允许我们直接在控制器内部为当前上下文(this)添加属性,而不需要显式注入scope 对象然后再在上面添加属性。以下代码片段示范了这种简化的语法:

<div ng-controller="MainCtrl as main">
 <button ng-click="main.clicked()">Click</button>
</div>

function MainCtrl(){
  this.name = "hello world";
}

MainCtrl.prototype.clicked = function (){
  alert("you clicked me");
}

        Angular 2 更进一步,直接删除了scope 对象。所有表达式都在特定UI 组件的上下文中执行。scope API 整体删掉之后使得Angular 2 得到了大幅度简化,我们不再需要显式注入scope 了,只要把属性直接添加到UI 组件上,然后再进行绑定操作即可。

依赖注入

      在JavaScript 领域,AngularJS 1.x 也许是市面上的第一个通过dependencyinjection (DI)引入inversion of control (IoC)机制的框架。DI 可以带来很多好处,比如:易测试性、更好的代码结构和模块化,以及更简洁明了。虽然在1.x 版本中DI 运行得相当不错,但是Angular 2 对它进行了进一步的发挥。因为 Angular 2 是基于最新web 标准构建的,所以它使用了ECMAScript 2016 装饰器(decorator)语法对使用DI的代码进行了注解。这里的装饰器与Python 中的装饰器或Java 中的注解非常类似。它们都可以使用反射机制来decorate(装饰)指定对象的行为。由于装饰器还没有标准化,也不被主流浏览器所支持,所以使用的时候需要经过中间转换步骤。

        一个对象通常有三种方式可以获得对其依赖的控制权:

            (1) 在内部创建依赖;

            (2)通过全局变量进行引用;

            (3)在需要的地方通过参数进行传递;

        依赖注入是通过第三种方式实现的。从功能上看,依赖注入会事先自动查找依赖关系,并将注入目标告知被依赖的资源,这样可以在目标需要时将资源注入进去。在编写依赖于其他对象或库的组件时,我们需要描述组件之间的依赖关系。在运行期,注入器会创建依赖的实例,并负责将它传递给依赖的消费者。AngularJS使用$injector(注入器服务)来管理依赖关系的查询和实例化。

        在运行时,任何模块启动时$injector都会负责实例化,并将需要的所有依赖传递进去。

//使用注入器加载应用
var injector = angular.injector(['ng','myApp']);
//通过注入器加载$controller服务
var $controller = injector.get('$controller');
var scope = injector.get('$rootScope').$new();
//加载控制器并传入一个作用域,同angularJS在运行时做的一样
var myController = $controller('MyController',{$scope: scope});

        在任何一个AngularJS应用中,都有$injector在进行工作,无论我们知道与否。当编写控制器是,如果没有使用[]标记或进行显示的声明,$injector就会尝试通过参数名腿短依赖关系。

    推断式注入声明

          如果函数没有明确的声明,AngularJS会假定参数名称就是依赖的名称。它会在内部调用函数对象的toString()方法,分析并提取出函数参数列表,通过$injector将这些参数注入进对象实例。

injector.invoke(function($http,greeter){});

注意!!!:JavaScript的压缩器通常会将参数名改写成简单的字符,以减小源文件体积(同时也会删除空格、空行和注释等),如果我们不明确地描述依赖关系,AngularJS将无法根据参数名称推断出实际的依赖关系,也无法进行依赖注入。注入过程只适用于未经过压缩和混淆的代码,因为AngularJS需要原始为经压缩的参数列表来解析。

    显式注入声明

           AngularJS提供显示方法来定义一个函数在被调用时需要用到的依赖关系。显示声明不受源代码被压缩和混淆的情况影响,依然能正常工作。通过$injector属性来实现显示注入声明的功能。函数对象的$injector属性是一个数组,数组元素的类型时字符串,它们的值就是需要被注入的服务名称。

var controllerFactory = function controller($scope, greeter){
 //控制器
};
controllerFactory.$inject = ['$scope','greeter'];

//应用控制器
angular.module('myApp',[])
.controller('myController', controllerFactory)
.factory('greeter',greeterService);

//获取注入器并创建一个新的作用域

var injector = angular.injector(['ng','myApp']),
    controller = injector.get('$controller'),
    rootScope = injector.get('$rootScope'),
    newScope = rootScope.$new();

//调用控制器

controller('MyController', {$scope: newScope});

注意!!!: 显示声明,参数顺序非常重要,因为$injector数组元素的顺序必须和注入参数顺序一一对应,这种方式可以在压缩后的代码中运行。

    行内注入声明

            我们在函数定义时从行内将参数传入,是AngularJS提供的行内注入声明,它避免在定义过程中使用临时变量。在定义一个AngularJS的对象时,行内声明的方式允许我们直接传入一个参数数组而不是一个函数。数组的元素时字符串,它们代表的是可以被注入到对象中的依赖的名字,最后一个参数就是依赖注入的目标函数对象本身。

angular.module('myApp').controller('myController',['$scope','greeter',function ($scope, greeter){

}]);

注意!!!:行内注入声明可以在压缩后的代码中正常运行。

参考资料

【美】Ari Lerner 著《AngularJS 权威教程》

转载时请注明:来自w-rain的个人博客

转载于:https://my.oschina.net/myrainspace/blog/1602633

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值