「Done is better than perfect.」

Angular in Action

by Jimmy Lv

MVVM: 双向绑定

很讽刺的是,需要使用 Vue 来演示 AngularJS 的 MVVM 概念,需要 React 来演示 Component,以及单向数据流。

Template&Directive

基于 DOM <=> Vitural DOM

ng-controller="MainCtrl as main"

content Editable

Model&View Data binding

"single-source-of-truth" 其实只需要关注 data,易测试,灵活性高

双向数据绑定,dirty check -> \$watch -> 影响性能

View 和 Model 应该分开?

React: 数据只会由 parent 流向 children,只会由逻辑流向页面,更好理解和维护。

onChange={this.handleChange.bind(this, "pass")} in React

Dependency Injection

动态语言、ES5 没有包管理/注入? -> Angular module -> ES6 or RequireJS

学习曲线

最开始只要 Controller&Directive 就实现了 hello world

但是一旦深入,就必须接受一大堆 Angular 自创术语

module

```

{{ message }}

</div>
angular.module('app', []);
angular.module('app').controller('MainCtrl', function ($scope){

$scope.message = 'hello'; ```

});

Controller

to expose data to our view via $scope & add functions to $scope

nested or multiple nested controllers 可以继承,每 ng-controller 指令会创建新的子级 scope,三层 div 结构,也就对应有三层 scope 继承关系的层级结构

不要操作具体的 DOM 和 filter 等其他事情,专注单个 view 的业务逻辑

Presentation logic should remain within views and directives.

相互间操作使用 Service(across app/module),再注入 controller

old? > controller as syntax : -> this = self . create a reference to this so that we don't lose context of our controller when we create/call functions within our controller.

\$scope

不显式注入\$scope 了,语法是这样:

function CtrlB() {
  this.a = 1;
  this.foo = function() {
  };
}

<div ng-controller="CtrlB as instanceB"></div>

在任意一个已有的作用域上调用\$new(),就能创建一个新的作用域:

var newScope = scope.$new(); 刚创建出来的作用域是一个“悬空”的作用域,也就是说,它跟任何界面模板都不存在绑定关系,创建它的作用域会成为它的$parent。这种作用域可以经过\$compile 阶段,与某视图模板进行融合。

Service

to share data

singletons that can be injected into controllers and other services: reusable

like \$http

最明显的 DI 体现

Lazily instantiated: not registering a service instance, but rather a factory function -> angular.module('myModule', []).factory('serviceId',

Test

Controller 的数据测试,

Jasmine spy (mock) a real browser alert.

Form

{{}} 只支持一部分 js 表达式,支持三元

angular.copy(user)

form 可以直接用 css

Promise \$q

Deferred:

\$q.defer() resolve(), reject(), and notify()

\$q(function(resolve, reject) {

$timeout(function() {
    if(Math.round(Math.random())) {
      resolve('data received!')
    } else {
      reject('oh no an error! try again')
    }
  }, 2000)

Promise:

then().then().finally()

catch(errorCallback) – shorthand for promise.then(null, errorCallback)

\$http - success() error()

Filters

Chaining built-in filters: <p ng-repeat="person in test.people | filter:search | orderBy:'name' | limitTo: 5">

Directive

add things like behaviors:

  • "A" is for attribute <div welcome></div> (default restrict property)
  • "E" is for element <welcome></welcome>
  • "C" is for class <div class="welcome"></div>
  • "M" for comment <!-- directive: welcome -->

functionalities:

addClass() removeClass()

<div entering="activeClass"></div>
function(scope, element, attrs) {
  element.bind("mouseenter", function(){
    element.addClass(attrs.entering);
  })
}

can be used in controller

\$Route

$routeProvider.when("/:firstName/:middleName/:lastName",
    {
      templateUrl: "app.html",
      controller: "AppCtrl",
      controllerAs: "app"
    }
  );

$routeParams.firstName + " " + $routeParams.middleName + " " + \$routeParams.lastName;