AngularJs concepts详解及示例代码

原版地址:http://code.angularjs.org/1.0.2/docs/guide/concepts

继续。。

一、总括

本文主要是angular组件(components)的概览,并说明他们如何工作。列表如下:

  1. statup - 依旧是hello world...改为Hello Kitty!
  2. runtime - 介绍angular的runtime
  3. scope - view与contorller的纽带(神马glue...胶)
  4. controller - app的行为(application behavior)
  5. model - app的数据
  6. view - 用户所看到的东东
  7. directives - HTML的语法扩展
  8. filters - 根据用户的本地格式,格式化数据
  9. injector - 加载我们的app(依赖管理之类)
  10. module - 配置injector
  11. $ - angular的命名空间(namespace)

二、启动(Startup)

下面描述angular是如何启动的(参考图表与下面的例子):

1. 浏览器加载HTML,将HTML标签转换为DOM对象;

2. 浏览器加载angular.js的脚本;

3. Angular等待DOMContentLoaded事件;

4. Angular寻找ng-app这个用于指定应用边界范围的directive;

5. 如果ng-app有指定module(也许是ng-app=”SomeApp”),将被用作配置$injector;

6. $injector用于创建$compile服务(service)以及$rootScope;

7. $compile服务用作“编译”(有点像遍历,然后做一点神秘的事情)DOM,并将其与对应的$rootScope连接。

8. ng-init 这个directive在对应的scope中创建name属性并对其赋予”Kitty”值;

9. 将“{{name}}”的值插入(interpolates)到表达式中,最终显示”Hello Kitty!”。

<!DOCTYPE html>
<html lang="zh-cn" ng-app>
<head>
  <meta charset="UTF-8">
  <title>Hello Kitty!</title>
  <style type="text/css">
    .ng-cloak {
      display: none;
    }
  </style>
</head>
<body>
<div ng-init="name='Kitty'">Hello {{name}}!</div>
<script src="../angular-1.0.1.js" type="text/javascript"></script>
</body>
</html>

由于今晚跟别人讨论一些东西,所以进度缓慢。。。又是那句。。。现在已经是夜深了。。。Angular,广告之后见!

==============================================

广告完毕。。。继续

三、Runtime

  这图表和后面的例子,描述了angular如何通过浏览器event-loop(所有的时间处理函数,以及timer执行的函数,会排在一个queue结构中,利用一个无限的循环,不断从queue中取出函数来执行,这个就是event-loop。来自http://wiki.nodejs.tw/nodejs_from_scratch/javascript-yunodejs/2-1-event-loop)来进行交互。

  1. 浏览器event-loop等待事件到来。事件来自于用户交互(DOM events)、timer事件(setTimeout)、network事件(服务端响应,XHR之类);

  2. 事件回调函数开始执行。这里进入javascript上下文(context)。这回调函数可以修改DOM结构。

  3. 当回调函数执行完毕后,浏览器退出javascript context,根据DOM的改变来重绘视图。

  Angular通过创建自己的事件处理循环(event processing loop),修改了一般的javascript流(flow)。这将Javascript分割成传统的和Angular的执行上下文(execution context)。只要是在Angular execution context 里面执行的操作,都拥有angular data-binding、异常处理(exception handling)、属性监视(property watching)等能力。我们可以通过在javascript使用$apply(),进入Angular execution context。但要记住一点,在大多数(angular的)地方(如controllers、services),处理事件的directive会为你调用$apply。手动调用$apply的场景,一般是当你实现自定义事件处理函数,或者处理第三方库的回调的时候。

  1. 通过调用scope.$apply(stimulusFn)进入angular execution context。stimulusFn就是我们想在angular execution context中执行的函数(含scope作为参数)或者angular合法的表达式。

  2. Angular执行stimulusFn,这通常会改变应用的状态(application state)。

  3. Angular进入$digest loop。这个loop由一个处理$evalAsync queue 和处理$watch list两个更小的循环组成。$digest loop会在model稳定之前保持迭代,即$evalAsync queue为空,而且$watch list没有检测到任何变化。

  4. $evalAsync queue被用作安排必须跳出当前堆栈帧(堆栈帧指的是在堆栈中为当前正在运行的函数分配的区域(或空间)。传入的参数、返回地址(当这个函数结束后必须跳转到该返回地址。译注:即主调函数的断点处)以及函数所用的内部存储单元(即函数存储在堆栈上的局部变量)都在堆栈帧中。http://book.51cto.com/art/200804/70915.htm C.1.1  堆栈帧)之外,但在浏览器视图绘制之前的工作。这通常是通过使用setTimeout(0)来实现。但setTimeout(0)这方法,会导致缓慢,或者在每个事件处理完毕后,浏览器绘制视图时,出现视图闪烁(angular有没有去解决这个问题?如何解决?)。

  5. $watch list是有可能在最近一次迭代中被修改的表达式的集合。如果(model)发生了改变,那么$watch 函数会被调用,从而达到对特定的DOM重新赋值的目标。

  6. 一旦Angular $digest loop 完成了(之前3提到的情况),离开angular和javascript的context后,浏览器紧跟着就会去重绘DOM,以响应变化。

  下面解释例子“Hello Kitty”(-_-!)是如何在用户在文本框输入文本时实现数据绑定(data-binding)效果。

  1. 编译阶段(compilation phase):

    a) ng-model和input directive在<input>中版定keydown事件监听器。

    b) {{name}}占位符(interpolation,不知道怎么翻译)(表达式)设置一个$watch以便在name发生改变时有所响应。

  2. 执行阶段(runtime phase):

    a) 在inut控件中按下”X”按钮,让浏览器触发一个keydown事件;

    b) input directive捕捉到文本框值的改变,然后调用$apply(“name = ‘X';”),在angular execution context中更新应用的model。

    c) Angluar将 “name = ‘X';”应用在model中。(model发生改变)

    d) $digest loop开始

    e) $watch list检测到name的值被改变了,然后再次解析{{name}}表达式,然后更新DOM。

    f) Angulart退出(angular) execution context,再依次退出keydown事件以及javascript execution context;

    g) 浏览器重绘视图,更新字符。

<!DOCTYPE html>
<html lang="zh-cn" ng-app>
<head>
  <meta charset="UTF-8">
  <title>Hello Kitty!</title>
  <style type="text/css">
    .ng-cloak {
      display: none;
    }
  </style>
</head>
<body>
  <input ng-model="name" class="ng-cloak"/>
  <p>Hello {{name}}!</p>
<script src="../angular-1.0.1.js" type="text/javascript"></script>
</body>
</html>

四、Scope

  scope的是负责检测model的变化,并作为表达式的执行上下文(execution context)。Scope是在一个类似于DOM结构的层次结构中嵌套的(据之前了解,划分可能跟controller有关)。(详情查看individual directive documentation,看看哪个directive会创建新的scope)

  下面的例子展示”name”这个表达式的值是根据它依赖(所属)的scope决定的,而且还包含了值查找的方式(类似Js的作用域链,自己没有就找老爸要)。

<!DOCTYPE HTML>
<html lang="zh-cn" ng-app>
<head>
  <meta charset="UTF-8">
  <title>scope</title>
  <style type="text/css">
    .ng-cloak {
      display: none;
    }
  </style>
</head>
<body>
<div class="ng-cloak" ng-controller="ControllerA">
  Hello {{name}}!;
</div>
<div class="ng-cloak" ng-controller="ControllerB">
  Hello {{name}}!;
  <div class="ng-cloak" ng-controller="ControllerC">
    Hello {{name}}!;
    <div class="ng-cloak" ng-controller="ControllerD">
      Hello {{name}}!;
    </div>
  </div>
</div>
<script src="../angular-1.0.1.js" type="text/javascript"></script>
<script type="text/javascript">
  function ControllerA($scope) {
    $scope.name = 'Kitty';
  }

  function ControllerB($scope) {
    $scope.name = 'Lcllao';
  }

  function ControllerC($scope) {
    $scope.name = 'Jeffrey';
  }

  function ControllerD($scope) {

  }
</script>
</body>
</html>

五、Controller

<!DOCTYPE HTML>
<html lang="zh-cn" ng-app>
<head>
  <meta charset="UTF-8">
  <title>Controller</title>
  <style type="text/css">
    .ng-cloak {
      display: none;
    }
  </style>
</head>
<body>
<div class="ng-cloak" ng-controller="ControllerA">
  Hello {{name}}!
  <button ng-click="doIt()">DoIt!!</button>
</div>
<script src="../angular-1.0.1.js" type="text/javascript"></script>
<script type="text/javascript">
  function ControllerA($scope) {
    $scope.name = 'Kitty';
    $scope.doIt = function() {
      $scope.name = "Handsome";
    };
  }
</script>
</body>
</html>

  Controller是在view背后的代码(-_-!)。它的职责是构建model,并通过回调函数,将其(model)推送到view中。View是当前scope到template(HTML)的映射(翻译得有点勉强...)。Scope是指挥model到view以及向controller发送event的纽带。

  Controller与view分离是很重要的,因为:

1.Controller是写在javascript中的。Javascript是命令式的(imperative)。命令(imperative)是描述应用程序行为的一个好方法。Controller不应该包含任何显示信息(的逻辑)(DOM引用或者HTML片段)

2.View模版是写在HTML里的。HTML是声明式的。声明式(的HTML)是描述UI的好方法。View不应该包含任何行为。

3.由于Controller不知道自己需要对应哪一个View,使得一个Controller可以(间接)使用多个View。这对于re-skinning(更换皮肤?)、其他设备特定的视图(例如手机与桌面)还有代码的可测性是很重要的。

六、Model

  Model,可以理解为数据对象。它被用作与模版结合,以产生视图。为了将model写入到视图中,model必须被scope所引用。与很多其他框架不一样,angular对model没有任何限制与要求。不需要额外添加class,也不需要通过特殊的特权方法去访问或者改变model。Model的数据类型,可以是原始的类型(string、number……),可以是键值对象({a:1,b:2}),也可以是函数(function() {…})。简要地说,angular的model只需要是一个普通的javascript对象。

七、View

  view是用户所能看到的东西。view诞生于模版。它与model结合,最终呈现为浏览器DOM。Angular采取一个对于其他很多模版系统来说,很不一样的方式去呈现View。

其他模版引擎:很多模版引擎,是通过建立带有特殊标记的HTML字符串来实现的。通常这些模版标记破坏了HTML的语法,这意味着不能通过一般的HTML编辑器去编辑代码(这个嘛…)。模版字符串传入模版引擎,与数据合并。最终生成HTML字符串。这些字符串一般通过.innerHTML的方式写入DOM中,促使浏览器呈现模版内容。当数据发生改变时,这个过程需要一次又一次地重复。模版的粒度与DOM更新的粒度一致。这粒的关键,是模版系统处理字符串。

Angular:Angular模版的不同之处,在于它是基于DOM的而不是基于字符串的。模版依然需要在HTML中写入一些字符串,但依旧是HTML(不是通过在里面嵌入模版)。浏览器把HTML转换为DOM,然后DOM成为了compiler(angular的模版引擎)的输入。Compiler查找directives,依次在model中设置watches。得出的结果,是一个一直更新的view,不需要重新拼接model与template。model成为了view的唯一数据来源(single source of truth)。

 八、Directives

  Directive是一个行为(例如之前文章的例子“躲猫猫”)或DOM转换(自定义标签,里面包含一组DOM),将其名称放在属性、标签名、class名里面都可以触发该directive。Directive允许你以声明的方式扩展HTML的标签。

  下面的例子,还有一些疑问。就是$render如何触发@_@

<!DOCTYPE HTML>
<html lang="zh-cn" ng-app="myDirective">
<head>
  <meta charset="UTF-8">
  <title>directive</title>
  <style type="text/css">
    .ng-cloak {
      display: none;
    }
  </style>
</head>
<body ng-controller="MyCtrl">
<div ng-model="content" contenteditable="true">My Little Dada</div>
<pre class="ng-cloak">modelValue = {{content}}</pre>
<button ng-click="reset()">reset(change model)</button>
<script src="../angular-1.0.1.js" type="text/javascript"></script>
<script type="text/javascript">
  angular.module("myDirective",[])
      .directive("contenteditable",function() {
        return {
          require:'ngModel',
          link:function (scope, element, attr, ngModel) {
            function setVal() {
              ngModel.$setViewValue(element.text());
            }

            // veiw -> model
            element.bind("keyup",function() {
              scope.$apply(setVal);
            });
            // model -> view
            ngModel.$render = function(val) {
              console.log("render running");
              element.html(val);
            };
            //init
            setVal();
          }
        }
      }
  ).controller("MyCtrl",function($scope) {
        $scope.reset = function() {
            $scope.content = "My Little Dada";
        };
      });
</script>
</body>
</html>

九、Filters

  Filters 扮演一个数据转换(格式化)的角色。通常他们是与地域有关的,不同地域也许会有不同的输出格式。他们在追随了Unix过滤器的精神与类似的语法:|  (pipe)

<!DOCTYPE HTML>
<html lang="zh-cn" ng-app>
<head>
  <meta charset="UTF-8">
  <title>filter</title>
  <style type="text/css">
    .ng-cloak {
      display: none;
    }
  </style>
</head>
<body>
<div ng-init="list = ['百度B','搜狗S','360','3SB']">

  数字格式化: 1233211234567 -> {{1233211234567|number}}<br/>
  数组过滤,然后通过json格式输出: <input ng-model="myFilterText" type="text"/><br/>
  {{list|filter:myFilterText|json}}<br/>
</div>
<script src="../angular-1.0.1.js" type="text/javascript"></script>
</body>
</html>

 十、Modules and the Injector

  Injector是一个服务定位器。每一个Angular应用,都会有一个单独的injector。Injector提供一个通过名称查找对象实例的途径。Injector会在内部cache中保持所有对象实例,所以重复调用相同的名称时,返回的都是同一个对象实例。如果对象不存在,那么它会请求实例工厂(instance factory)去创建一个新实例。

  Module是一个配置injector的实例工厂的方法,被称为”provider”。

 // Create a module
  var myModule = angular.module('myModule', [])

  // Configure the injector
  myModule.factory('serviceA', function() {
  return {
  // instead of {}, put your object creation here
  };
  });

  // create an injector and configure it from 'myModule'
  var $injector = angular.injector('myModule');

  // retrieve an object from the injector by name
  var serviceA = $injector.get('serviceA');

  // always true because of instance cache
  $injector.get('serviceA') === $injector.get('serviceA');//true

  但是injector的真正牛X的地方在于它可以用于调用方法和”instantiate” type。这个美妙的特性是允许method和types请求他们所依赖的资源,而不是寻找他们。

 // You write functions such as this one.
  function doSomething(serviceA, serviceB) {
  // do something here.
  }

  // Angular provides the injector for your application
  var $injector = ...;

  ///////////////////////////////////////////////
  // the old-school way of getting dependencies.
  var serviceA = $injector.get('serviceA');
  var serviceB = $injector.get('serviceB');

  // now call the function
  doSomething(serviceA, serviceB);

//上面是传统的老方法~下面是angular说自己的牛X方法

  ///////////////////////////////////////////////
  // the cool way of getting dependencies.
  // the $injector will supply the arguments to the function automatically
  $injector.invoke(doSomething); // This is how the framework calls your functions

  注意,我们唯一需要写的,就是我们的function,在function的arguments中列出方法依赖的资源即可!当angular调用function时,他会使用”call”方法,自动填充function agruments。

  留意下面的例子中是如何在constructor中列出依赖的。当ng-controller实例化controller时,将自动提供所依赖的资源。没有必要去创建、寻找、创建injector引用来加载依赖资源。

<!DOCTYPE HTML>
<html lang="zh-cn" ng-app="timeExample">
<head>
  <meta charset="UTF-8">
  <title>injector</title>
  <style type="text/css">
    .ng-cloak {
      display: none;
    }
  </style>
</head>
<body>
<div ng-controller="ClockCtrl" class="ng-cloak">
  Current time is : {{time.now}}
</div>
<script src="../angular-1.0.1.js" type="text/javascript"></script>
<script type="text/javascript">
  angular.module("timeExample", []).factory("myClock", function ($timeout) {
    var time = {};
    (function tick() {
      time.now = new Date().toString();
      $timeout(tick, 1000);
    })();
    return time;
  });
  /**
   *
   * @param $scope
   * @param myClock 这里自动插入了依赖的myClock!!
   * @constructor
   */
  function ClockCtrl($scope,myClock) {
    $scope.time = myClock;
  }
</script>
</body>
</html>

十一、Angular Namespace

为了防止名称冲突,angular会在object的名称中加入前缀$。请不要在代码中使用$前缀以避免冲突。(-_-!! )

以上就是关于AngularJS concepts 的资料整理,后续继续添加相关文章,谢谢大家对本站的支持!

(0)

相关推荐

  • AngularJs Using $location详解及示例代码

    一.What does it do? $location服务分析浏览器地址栏中的URL(基于window.location),让我们可以在应用中较为方便地使用URL里面的东东.在地址栏中更改URL,会响应到$location服务中,而在$location中修改URL,也会响应到地址栏中. $location服务: 暴露当前浏览器地址栏的URL,所以我们可以 1.注意和观察URL 2.改变URL 当用户做以下操作时,与浏览器一起同步URL: 1.改变地址栏 2.单击后退或者前进按钮(或者点击一个历

  • AngularJs Understanding the Model Component

    在angular文档讨论的上下文中,术语"model"可以适用于单一对象代表一个实体(例如,一个叫" phones"的model,它的值是一个电话数组.)或者作为应用的全部数据Model(所有实体). 在angular中,model可以是任意数据,可以通过angular的scope对象的属性来获取model.属性的名称是model的标识,值可以是任意javascript对象(包括数组和原始数据). javascript想成为model的唯一的条件是对象必须作为一个s

  • AngularJs bootstrap搭载前台框架——js控制部分

    这个简单的框架最后只剩下了js的控制部分了,angular框架有自己的逻辑部分,有自己的controller和service层,由于我们可能要用到angular的一些内置的resource和cookie,所以我们需要再加入angular的一些lib: --------------index.html------------------ <script src="lib/angular/angular-strap.js"></script> <script

  • AngularJs 国际化(I18n/L10n)详解

    一.I18n and L10n in AngularJS 1. 什么是I18n和L10n? 国际化(Internationalization),简称I18n,是让产品开发在一个他们可以简单地对产品进行语言.文化的本地化的方法的规范.本地化(Localization),简称L10n,一个使得应用.文本有适应特殊的文化或者语言市场的能力的规范.对于应用开发者,使一个程序国际化,意味着需要从程序中抽取所有字符串和其他区域较为特别的地方(例如日期和货币格式).使一个程序本地化,意味着需要提供根据I18n

  • AngularJs Scope详解及示例代码

    一.什么是Scope? scope(http://code.angularjs.org/1.0.2/docs/api/ng.$rootScope.Scope)是一个指向应用model的object.它也是expression(http://www.cnblogs.com/lcllao/archive/2012/09/16/2687162.html)的执行上下文.scope被放置于一个类似应用的DOM结构的层次结构中.scope可以监测(watch,$watch)expression和传播事件.

  • AngularJs Understanding the Controller Component

    在angular中,controller是一个javascript 函数(type/class),被用作扩展除了root scope在外的angular scope(http://www.jb51.net/article/91749.htm)的实例.当我们或者angular通过scope.$new API(http://docs.angularjs.org/api/ng.$rootScope.Scope#$new)创建新的child scope时,有一个选项作为方法的参数传入controller

  • AngularJs Injecting Services Into Controllers详解

    把service当作被依赖的资源加载到controller中的方法,与加载到其他服务中的方法很相似. 由于javascript是一个动态语言,DI不能弄明白应该通过static types(like in static typed languages)注入哪一个service.因此,我们需要通过$inject属性指定service名称, 它是一个包含需要注入的service名称的字符串数组.service ID顺序的重要性:工厂方法中的参数顺序,与service在数组中的顺序一致.工厂方法的参数

  • AngularJs expression详解及简单示例

    表达式(Expressions)是类Javascript的代码片段,通常放置在绑定区域中(如{{expression}}).表达式通过$parse服务(http://code.angularjs.org/1.0.2/docs/api/ng.$parse)解析执行. 例如,以下是angular中有效的表达式: 1+2 3*10 | currency user.name 一.Angular表达式 vs. Js 表达式 这很容易让人将angular视图表达式联想为javascript表达式,但这并不完

  • AngularJs E2E Testing 详解

    当一个应用的复杂度.大小在增加时,使得依靠人工去测试新特性的可靠性.抓Bug和回归测试是不切实际的. 为了解决这个问题,我们建立了Angular Scenario Runner,模仿用户的操作,帮助我们去验证angular应用的健壮性. 一.   总括 我们可以在javascript中写情景测试(scenario test),描述我们的应用发生的行为,在某个状态下给与某些互动.一个情景包含一个或者多个"it"块(我们可以将这些当作对我们应用的要求),依次由命令(command)和期望(

  • AngularJs Dependency Injection(DI,依赖注入)

    一.Dependency Injection(依赖注入) 依赖注入(DI)是一个软件设计模式,处理代码如何得到它所依赖的资源. 关于DI更深层次的讨论,可以参观Dependency Injection(http://en.wikipedia.org/wiki/Dependency_injection),Inversion of Control(http://martinfowler.com/articles/injection.html),也可以参观软件设计模式的书. 1. DI in a nu

  • AngularJs Modules详解及示例代码

    一.什么是Module? 很多应用都有一个用于初始化.加载(wires是这个意思吗?)和启动应用的main方法.angular应用不需要main方法,作为替代,module提供有指定目的的声明式,描述应用如何启动.这样做有几项优点: 这过程是声明描述的,更加容易读懂. 在单元测试中,不需要加载所有module,这对写单元测试很有帮助. 额外的module可以被加载到情景测试中,可以覆盖一些设置,帮助进行应用的端对端测试(end-to-end test). 第三方代码可以作为可复用的module打

  • AngularJs Forms详解及简单示例

    控件(input.select.textarea)是用户输入数据的一种方式.Form(表单)是这些控件的集合,目的是将相关的控件进行分组. 表单和控件提供了验证服务,所以用户可以收到无效输入的提示.这提供了更好的用户体验,因为用户可以立即获取到反馈,知道如何修正错误.请记住,虽然客户端验证在提供良好的用户体验中扮演重要的角色,但是它可以很简单地被绕过,因此,客户端验证是不可信的.服务端验证对于一个安全的应用来说仍然是必要的. 一.Simple form 理解双向数据绑定的关键directive是

  • AngularJs Understanding Angular Templates

    angular template是一个声明规范,与model.controller的信息一起,渲染成用户在浏览器中所看到的视图.它是静态的DOM,包括HTML.CSS.angular特别的元素和angular指定的元素属性.angular元素和属性指示angular去扩展行为以及将template DOM转换为动态视图的DOM. 下面是我们可以在template中使用的angular元素已经元素属性的类型: Directive(http://www.jb51.net/article/91739.

  • AngularJs Creating Services详解及示例代码

    虽然angular提供许多有用的service,在一些特别的应用中,我们会发现编写自定义service是很有用的.如果我们想做这件事,我们首先要在module中注册一个service工厂方法,可以通过Module.factory api(http://docs.angularjs.org/api/angular.module)或者在module配置方法中直接通过$provide api(http://docs.angularjs.org/api/AUTO.$provide). 所有angular

  • AngularJs Managing Service Dependencies详解

    angular允许service将其他service声明为依赖,使用在自身实例化时使用的构造函数中. 为了声明依赖,我们需要在工厂方法声明中指定它们,并且在工厂方法中通过$inject属性(字符串标识数组)或者使用array notation. 通常$inject属性声明可以被丢弃(即http://www.jb51.net/article/91815.htm中提到的隐式依赖注入,但这个是实验属性,在而且在压缩混淆后会失效,慎用!). 使用array notation function myMod

随机推荐