AngularJS -1

关于AngularJS中的Scope体系:
AngularJS会在程序启动时创建一个$rootScope实例,然后再去搜索HTML DOM 树代码中
如果遇见ng- 元素,它就会为它们调用Scope.$new()方法来创建一个子 $scope,
而且每个子Scope内部都有一个$parent 属性指向其上一级Scope对象。

如此一个DOM树中会有很多范围创建指令,所以会有很多scope被创建出来。
它们都是以$rootScope为根的树形结构关系。它也是一个小型化了的DOM结构。

var WorldCtrl = function ($scope) {
    $scope.population = 7000;
    $scope.countries = [
        {name: 'France', population: 63.1},
        {name: 'United Kingdom', population: 61.8},
    ];
};


        

  •         {{country.name}} has population of {{country.population}}
        

  •     

        World's population: {{population}} millions

这里我们创建了一个新变量country,把它暴露在$scope 里一边在页面上绑定。
但是由于重复创建会覆盖之前的,所以Angluar采取了为集合中的每一个元素都创建一个scope
新创建的Scope会完全匹配DOM树结构。

不同的DOM元素对应着不同的Scope对象,使用变量从相应的Scope中渲染模板。
上例中每个

  • 元素会对应一个自己的scope,可以在它里面定义。

    如此我们可以给WorldCtrl管理的scope定义一个worldsPercentage函数
    $scope.worldsPercentage = function (countryPopulation) {
        return (countryPopulation / $scope.population)*100;
    }
    我们就可以在ng-repeat指令里随便使用了,因为它们都是它的子集。


  •     {{country.name}} has population of {{country.population}},
        {{worldsPercentage(country.population)}} % of the World's population
  • Scope的继承采用原型继承方式,当我们读取一个属性时,它会沿着继承链逐层向上寻找 。


    var HelloCtrl = function ($scope) {
    };


    Hello, {{name}}



    Say hello to:

    Hello, {{name}}!



    我们可以使用$parent.propertyName 来显式引用父Scope中定义的变量。

    这种做法是建立在DOM树结构不变的基础上的,但如果在元素上层插入另外一个DOM
    元素时,显然$parent就发生的变化,所以尽量避免这种显式的使用方法。

    另外的一种解决办法是将属性绑定到一个对象,而不是直接绑定到scope的属性。


    Hello,{{thing.name}}



        Say hello to:
        

    Hello,{{thing.name}}!




    如此只是在应用程序范围内定义了一个对象thing,所以各个级别的Scope都能访问到。

    Scope层级和事件系统:
    Scope的层级体系可以用作事件总线。
    AngularJS允许我们在Scope层级体系内传递命名事件和其负载。
    事件可以从任何scope中被发出,分为上行$emit或者下行$broadcast在Scope层级体系中进行。

    AngularJS核心服务和指令使用该事件总线来标识应用程序状态的重要变化。
    比如我们可以监听从$rootScope发出的$locationChangeSuccess事件,来当浏览器中的URL发生变化采取相应的处理。
    $scope.$on('$locationChangeSuccess',function(event,newUrl,oldUrl){
    });

    $on()方法可以在任意scope实例上调用,用于注册一个scope事件处理器。
    该处理器函数将把event对象作为第一个参数,后续的参数将跟事件的负载和事件类型相关。

    跟DOM事件类似,我们在一个event对象上调用 preventDefault()和stopPropagation()方法
    将会阻止事件继续在scope层级体系内传播。
    其中stopPropagation() 用于从下向上的$emit产生事件。

    事件在scope层级体系内传递将会为许多问题带来极好的解决方案。
    尤其是有关全局,异步的状态发生变化时通知某些元素。不过,这种方式现实中使用较少。
    通常我们使用的双向数据绑定来解决。
    在整个AngularJS框架中,只有三个事件被发射
    $includeContentRequested
    $includeContentLoaded
    $viewContentLoaded
    和七个事件被广播:
    $locationChangeStart
    $locationChangeSuccess
    $routeUpdate
    $routeChangeStart
    $routeChangeSuccess
    $routeChangeError
    $destroy

    优先使用数据双向绑定方案。

    Scopes的生命周期
    Scopes用于提高隔离的空间避免变量名冲突。
    Scopes用于分层组织管理内存空间。

    当一个 scope不再需要时就会被销毁,在其内定义的model和功能函数都将一并被垃圾收集器收回。

    新的scope一般都是被scope的创建指令负责创建和销毁。
    也可以通过手动调用scope的$new()和$destroy()方法来完成创建和销毁。

    关于视图:
    AngularJS使用HTML语言以及增强HTML元素来定义页面。
    AngularJS在浏览器将标记文本转化为DOM树后切入并沿着DOM结构逐步解析。
    只要遇到它的指令,AngularJS就会执行它自己的逻辑将指令转化成动态部分展示。

    Angular依托于合法的DOM树,它需要跟HTML的DOM树 类似于创建一个domain-specific language(DSL) 
    来告诉浏览器如何处理新的增强元素。


    AngularJS本身定义了一个顶级的命名空间angular,它下面定义了很多方便的属性和函数。
    module() 就是用来定义一个模块空间的函数。
    module 用作管理Angular其它对象的容器,它管理诸如controllers,services等)
    angular.module('moduleName',[dependencyList]) 返回一个module对象。

    定义完成module后,我们还需要把它放置到DOM结构中,通知AngularJS它的存在,否则它没有运行的入口。

    对象协作:
    AnglarJS提供了module来组织管理相互协作的对象,它不仅仅可以注册框架可以直接调用的对象(controllers,filters等)
    还可以注册开发人员定义的任意对象。

    Module模式在我们组织应用程序代码时非常有用,AngularJS对其的利用更进一步。
    出了注册对象到一个命名空间外,它还能通过声明描述这些对象之间的依赖关系。

    var NotificationsService = function () {
    this.MAX_LEN = 10;
    this.notificationsArchive = new NotificationsArchive();
    this.notifications = [];
    };
    NotificationsService.prototype.push = function (notification) {
    var newLen, notificationToArchive;
    newLen = this.notifications.unshift(notification);
    if (newLen > this.MAX_LEN) {
        notificationToArchive = this.notifications.pop();
            this.notificationsArchive.archive(notificationToArchive);
        }
        };
        NotificationsService.prototype.getCurrent = function () {
        return this.notifications;
    };

    服务注册
    AngularJS中有一个专门的服务$provide 用于注册不同的对象创建方法。
    注册的方法会被$injector 截取器截取后提供对象实例。

    $injector服务创建具体的对象,整个生命周期过程中Angular只会截取创建方法一次
    创建一个单独的对象实例。
    也就是所$injector创建的对象实例是单例模式的,每一个运行的应用程序只能有一个。

    AngularJS的Module只是保持这些对象实例,这些对象实例的创建是由我们来控制的。

    最简单的事Value方法:
    var myMod = angular.module('myMod', []);
    myMod.value('notificationsArchive', new NotificationsArchive());
    使用该方法注册的对象,一般不会依赖其它对象。属于简单对象。

    Value()注册无依赖的简单对象。

    Service方法:
    当我们需要的对象有依赖时,我们就不能用value方法定义了。
    最简单的注册一个有其它对象依赖的对象的方法是service(),它用来注册一个构造函数。
    myMod.service('notificationsService',NotificationsService);
    var NotificationsService = function (notificationsArchive) {
        this.notificationsArchive = notificationsArchive;
    };

    Service 方法注册有依赖的对象构造函数。

    注意:在AngularJS世界里,service既可以是注册构造函数或者由AngularJS DI管理的任意单例对象的方法。

    实际中,Service不太常用,主要是注册已有的构造函数,让AngularJS可以使用这些构造函数创建对象。


    Factory()
    它是另一个为对象创建注册方法的函数。
    它比Service()方法更加灵活一些,因为我们可以注册任意的对象创建函数,而不一定非是构造函数。

    myMod.factory('notificationsService',function(notificationsArchive){
        var MAX_LEN = 10;
        var notifications = [];
        return {
            push:function (notification) {
            var notificationToArchive;
            var newLen = notifications.unshift(notification);
            //push method can rely on the closure scope now!
            if (newLen > MAX_LEN) {
            notificationToArchive = this.notifications.pop();
            notificationsArchive.archive(notificationToArchive);
            }
            },
            // other methods of the NotificationsService
        };

    AngularJS使用factory函数来注册返回对象,它可以是任意的JS对象,包括function对象。

    该方法是AngularJS依赖系统中最为常用的获取对象的方式。
    它非常灵活,可以包含非常精致的对象创建逻辑。
    它是标准函数,我们可以使用private等范围限制变量,对一些内部逻辑进行封装。

    Constant()
    在一个模块范围内定义常量并注入到其它合作对象时,使用该方法。
    myMod.constant('MAX_LEN', 10);
    它在创建服务时非常有用,能够跨多应用程序共享。唯一问题时,它要求在定义时必须设置初始值。

    Provider()
    是上面介绍的所有方法的通用版本。
    它被定义成一个函数,该函数必须返回一个包含$get属性的对象。
    而$get属性是一个工厂函数,它被调用时会返回一个service实例。

    我们可以把provider认为是一个嵌入了一个工厂方法的对象。
    Provider方法返回一个对象,该对象可以包含额外的属性和方法,用于在$get()方法被调用前
    设置配置可选项值,以及更加复杂的配置逻辑。

    模块的生命周期:
    AngularJS支持多种对象的创建方式。其中Provider是最为特别的,它在生产对象实例时支持更加
    深入的配置设置。
    为了支持provider,AngularJS 将module的生命周期划分为两个阶段。
    配置阶段和运行阶段
    配置阶段主要完成所有配方方法的调用和配置
    运行阶段则主要是实例化后的一些逻辑执行。

    myMod.config(function(notificationsServiceProvider){
        notificationsServiceProvider.setMaxLen(5);
    });
    而运行阶段,我们可以认为是应用程序的主函数,与其它语言不同的是AngularJS
    模块可以有多个配置和运行块。
    一个运行的应用程序其实是一些相互协作的对象集合。
    它可以有多个入口。

    angular.module('upTimeApp', []).run(function($rootScope) {
        $rootScope.appStarted = new Date();
    });


    两个阶段的不同注册方法:
    Variable,Service,Factory在配置阶段不能注册
    而 Constant和Provider是可以在配置阶段注册的
    运行阶段能够注册的方法有Constant,Variable,Service,Factory等。
    注意Provider不能在运行阶段注册。


    模块之间的依赖关系:我们可以将相关的服务放到一个module里,创建可以重用的service类库。
    angular.module('application', ['notifications', 'archive'])

    顶层的module可以声明依赖它所需要的所有模块。
    Services可以依赖其它services,values,和constants

    服务和它们的跨模块可见性:
    我们可以在某个字模块里定义一个service然后将它注入到父模块中使用。
    angular.module('app', ['engines'])
        .factory('car', function ($log, dieselEngine) {
        return {
            start: function() {
                $log.info('Starting ' + dieselEngine.type);
            };
        }
    });
    angular.module('engines', [])
        .factory('dieselEngine', function () {
            return {
                type: 'diesel'
            };
    });

    兄弟模块定义的内容,相互之间也是可见的。
    angular.module('app', ['engines', 'cars'])

    angular.module('cars', [])
        .factory('car', function ($log, dieselEngine) {
            return {
                start: function() {
                    $log.info('Starting ' + dieselEngine.type);
                }
        };
    });
    angular.module('engines', [])
        .factory('dieselEngine', function () {
            return {
                type: 'diesel'
            };
    });

    在一个应用程序模块中定义的服务在其它所有模块中都是可见的,也就是说模块的层级不会
    影响所有定义服务的可见性。
    在应用程序启动时,AngularJS会将所有模块中的服务定义都集中到一个应用程序的全局空间内。
    所以,所有服务必须是单例模式的。

    我们在使用依赖对象而又不想使用其某个方法定义时,可以直接重新定义该方法。
    angular.module('app', ['engines', 'cars'])
        .controller('AppCtrl', function ($scope, car) {
            car.start();
    });

    angular.module('cars', [])
        .factory('car', function ($log, dieselEngine) {
            return {
                start: function() {
                    $log.info('Starting ' + dieselEngine.type);
                };
            }
        })
        .factory('dieselEngine', function () {
            return {
                type: 'custom diesel'
            };
    });


    JQuery作为一个类库用于简化DOM操作,比如document遍历,事件处理,动画,Ajax交互等。
    AngularJS是一个完整的框架,它是以model为中心的编程模式,而Jquery则是以DOM为中心的

    转载于:https://my.oschina.net/u/924064/blog/822850

    你可能感兴趣的:(AngularJS -1)