AngularJS 笔记

jopen 9年前

Module

  • ng-app 可以不必赋值:<div ng-app> 即合法
  • Module :app 的不同组件——controllers,services,filters,directives 的容器
  • module 的构造函数有两个参数:第一个字符串是本 module 的名字,第二个参数是其依赖的其他 module
  • 一个 html 文档只有第一个 ng-app 能自动载入(auto-bootstrap),其他 app 要手动 angular.bootstrapng-app 不可嵌套。一般可以使用注入依赖添加其他 module,除非明确需要载入多个 app 的话。

Dependency Injection

  • 注入依赖是一种用于处理对象和函数如何被创建以及它们如何获取依赖的软件设计模式。angular 的一切组件都由注入依赖创建并连接在一起。angular 中,DI 的容器名为 injector
  • 依赖 这个概念近似于父类,注入依赖类似于 多重继承

Model

  • ng-modelng-bind 分别为数据绑定的 设定取值 (于 $scope 内)

    <input ng-model="foo" />  <p ng-bind="foo" />
  • {{ variable }} 的效果和 ng-bind 相同,使用 ng-bind 的一个好处在于可以避免与其他(如 django)模板系统的冲突。

Controller

  • controller 是一个以 $scope 为参数的函数。他通过修改 $scope.var 来实时改变视图。

  • 也可以添加方法:

    $scope.double = function(num) {return num*2 ; } ;    lang:html  <input ng-model="num" />{{ double(num) }}
  • <ng-controller=""> 的 controller 内容会在该 html 元素被加载时阻塞式执行,也有可能是在 module 被加载时执行

  • 标准的 controller 声明方式为使用数组符号

    someModule.controller('MyController', ['$scope', 'dep1', 'dep2', function($scope, dep1, dep2) {  ...  $scope.aMethod = function() {  ...  }  ...  }]);

Service

  • 把 controller 中与 view 无关的业务逻辑,拿出来做成可复用的独立 module,就是 service。如 Ajax

  • 要想在一个 module 中使用另一个 module 的 service,就要把 service 放进第二构造函数的那个列表中,这个过程也被称为 依赖注入

  • 每个依赖于 service 的组件都能得到一个专属的 service 实例,该实例是由 service factory 生成的

  • service 通常以 $ 开头

  • 凡是被注入的依赖都要按顺序出现在函数的参数列表中,否则不能使用。也可以给他们起别名,如下例 win 代表 $window

    .controller('aCtrl',['$scope', '$window', function($scope,win){      win.alert("test")  }])
  • 通过 provide 在 module 的 config 函数内注册一个 service:

    angular.module('myModule', []).config(function($provide) {  $provide.factory('serviceId', function() {    var shinyNewServiceInstance;    //factory function body that constructs shinyNewServiceInstance    return shinyNewServiceInstance;  });  });

Scope

  • $scope 在 DOM 结构中是可继承的。每一次 ng-controller 指令都会新建一个子scope。子scope可以访问上层 DOM 中指定的 $scope 属性。
  • $scope 其实是一个 angular 内建 service

Template

  • view 就是 DOM,是 controller 数据在 html 上的投影。

Filter

  • 过滤器的机制都是创建一份副本,处理之,然后返回该副本

Ajax

  • $http.get("url").success(function(data){})
  • $http.post('/someUrl', {msg:'hello word!'})

POST 方法的默认编码方式是:Content-Type: application/json ,而非 jquery 的 Content-Type: x-www-form-urlencoded 。因此基于后一种编码方式的后台框架,如 django,就无法在 request.POST 中正确提供 POST 数据。因为真正的数据被按照 JSON 格式编码在了 request 的 body 里面。解决方法要么在 ajax 参数里显示指定编码格式,要么在后台 json.loads(request.body) 但后一种方法要做额外的参数检查,所以最好还是在前段改变编码格式。

UI Bootstrap 的 tab 和 dropdown

UI Bootstrap 提供了几个便捷的 推ter bootstrap 组件封装,其中包含 tab 和 dropdown 。但新组件的接口都还比较简单,如 tabset 就默认不包含 dropdown 。

tabset/tab 组件的实际行为,其实还是将标签自动转换为 bootstrap 的传统格式,因此仍可以通过传统方式创建 dropdown 标签:

<tabset>      <tab></tab>      ...      <li class="dropdown">          <a class="dropdown-toggle">更多</a>          <ul class="dropdown-menu">              <tab></tab>              ...          </ul>      </li>  </tabset>

但这种方式会有一个小问题就是:点击下拉菜单中的标签页后,下拉菜单不会自动关闭。这时候就要使用 dropdown 组件的自带接口来实现了,只需改一下 <li class="dropdown"> 标签:

<li dropdown is-open="dropdown_open">      <a class="dropdown-toggle">          更多 <span class="caret"></span>      </a>      <ul class="dropdown-menu">          <tab ng-click="dropdown_open=!dropdown_open"></tab>          ...      </ul>  </li>

这里使用 is-open 属性的前提是添加 dropdown 指令,并且要注意去掉 class="dropdown" 属性,否则会报错。

多大程度上使用动态页面和异步请求。

  • 异步请求仅用在非首页标签页或首页标签页中体积较大的内容,如广告和内容图片,logo 最好也同步加载,可以做图片优化
  • 异步请求不要用在用户的第一目标元素上,不论加载快慢,否则会影响用户体验,比如淘宝提交退货申请后的页面,显示对方还有 XX 时间做出反应的元素就使用了异步请求,导致用户会看到 {{}} 模板标签。
  • 动态/静态页面的选择取决于页面本身的属性,一个确认标准为,页面之间是否有明确的继承结构。从属关系会导致用户本能地使用后退按钮,动态内容应尽可能用于小元素,或用于 页面级元素(如标签页)时,保证不同页面之间在结构上是平级的。

来自:http://my.oschina.net/lionets/blog/345365