使用AngularJS  进行Hybrid App 开发已经有一年多时间了,这里做一个总结.

一、AngularJS 初始化加载流程

1、浏览器载入HTML,然后把它解析成DOM。
2、浏览器载入angular.js脚本。
3、AngularJS等到DOMContentLoaded事件触发。
4、AngularJS寻找ng-app指令,这个指令指示了应用的边界。
5、使用ng-app中指定的模块来配置注入器($injector)。
6、注入器($injector)是用来创建“编译服务($compile service)”和“根作用域($rootScope)”的。
7、编译服务($compile service)是用来编译DOM并把它链接到根作用域($rootScope)的。
8、ng-init指令将“World”赋给作用域里的name这个变量。
9、通过{{name}}的替换,整个表达式变成了“Hello World”。

二、AngularJS Provider/Service/Factory

1、什么是 provider ?

provider 可以为应用提供通用的服务,形式可以是常量,也可以是对象。

比如我们在 controller 里注入进来的 $http, $scope 都可以认为是 provider。

app.controller('MainCtrl', function ($scope, $http) {

  $http.get(....).then(.....);

}

2、provider  

现在让我们自己来定制一个 provider

// 方法 1
$provide.provider('test', { n:1; $get: function () { return n; }; }); // 方法 2
$provide.provider('test', function () { this.n = 2; this.$get = function () { return n; }; }); // 使用
app.controller('MainCtrl', function ($scope, test) {
$scope.test = test;
});

  

让我们看看 provider 的内部实现代码

function provider(name, provider_) {

  if (isFunction(provider_)) {

      provider_ = providerInjector.instantiate(provider_);

  }

   if (!provider_.$get) {

       throw Error('Provider ' + name + ' must define $get factory method.');

   }

   return providerCache[name + providerSuffix] = provider_;

}

可以看到 provider 的基本原则就是通过实现 $get 方法来进行单例注入,使用时获得的就是 $get 执行后的结果。

3、factory

那如果每次都要写一个 $get 是不是很麻烦? OK,所以我们有了 factory。 factory 可以说是 provider 的变种, 方法中的第二个参数就是 $get 中的内容。

// 定义 factory

$provide.factory('dd', function () {

   return new Date();

});

// 使用

app.controller('MainCtrl', function ($scope, dd) {

    $scope.mydate = dd;

});

  

factory 的实现源代码:

function factory(name, factoryFn) {

 return provider(name, {

   $get: factoryFn

});

}

  

4、service

在 factory 的例子中我们还是需要 new 一个对象返回,而 service 就更简单了,这一步都帮你省了, 他的第二个参数就是你要返回的对象类, 也就是 new 的哦给你工作都不用你做了。够清爽吧?

// 定义 service

$provide.service('dd', Date);

下面是 service 的实现源代码:

function service(name, constructor) {

  return factory(name, ['$injector', function($injector) {

       return $injector.instantiate(constructor);

   }]);
}

然后 factory 和 service 带来代码精简的同时也损失了一些特性。 provider 定义的服务是可以通过模块 config 来配置的。

三、AngularJS 动态添加元素和删除元素

$scope.userName='Welcome to Angular World!';
$scope.test = function test(){
console.log('Angular 动态添加元素');
} //通过$compile动态编译html
var html="<div ng-click='test()'>}</div>";
var template = angular.element(html);
var mobileDialogElement = $compile(template)($scope);
angular.element(document.body).append(mobileDialogElement); // remove移除创建的元素
var closeMobileDialog = function () {
if (mobileDialogElement) {
mobileDialogElement.remove();
}

四、AngularJS 事件广播与接收 

发送消息: $scope.$emit(name, data) 或者 $scope.$broadcast(name, data);

接收消息: $scope.on(name,function(event,data){ });

区别: $emit 广播给父controller   $broadcast 广播给子controller

broadcast 是从发送者向他的子scope广播一个事件。

这里就是ParentController发送, ParentController 和 ChildController 会接受到, 而MainController是不会收到的

$emit 广播给父controller,父controller 是可以收到消息

$on 有两个参数function(event,msg)  第一个参数是事件对象,第二个参数是接收到消息信息

 

angular.module('onBroadcastEvent', ['ng'])
.controller('MainController', function($scope) {
$scope.$on('To-MainController', function(event,msg) {
console.log('MainController received:' + msg);
});
})
.controller('ParentController', function($scope) {
$scope.click = function (msg) {
$scope.$emit('To-MainController',msg + ',from ParentController to MainController');
$scope.$broadcast('To-ChildController', msg + ',from ParentController to ChildController');
$scope.$broadcast('To-BrotherController', msg + ',from ParentController to BrotherController');
}
})
.controller('ChildController', function($scope){
$scope.$on('To-ChildController', function(event,msg) {
console.log('ChildController received:' + msg);
});
})
.controller('BrotherController', function($scope){
$scope.$on('To-BrotherController', function(event, msg) {
console.log('BrotherController received:' + msg);
});
});

五、AngularJS Promise Deferred实例

var app = angular.module('app', ['autocomplete']);
app.factory('Suggestion',
function($http, $q, $timeout){
var suggestion = new Object();
suggestion.getData = function(keyword) {
var deferred = $q.defer();
$http.get('http://codesearch.sinaapp.com/search.php',
}).success(function(data){
deferred.resolve(data);
});
return deferred.promise;
}
return suggestion;
});
app.controller('MySuggestionCtrl',
function($scope, $sce,Suggestion){
$scope.autoComplete = function(keyword){
if(keyword){
Suggestion.getData(keyword).then(function(data){
var dataList = data.split('|');
$scope.dataList = dataList;
});
}
}
});

 多个Promise实例:

var data2="222";
var promises = [];
var deffered1 = $q.defer();
var deffered2 = $q.defer();
$timeout(function(){
deffered1.resolve(data1);
},2000);
$timeout(function(){
deffered2.resolve(data2);
},2000);
promises.push(deffered1.promise);
promises.push(deffered2.promise);
$q.all(promises).then(function(data){
console.log(data);
});

输出: ["111", "222"] 这个一个数组对象顺序与push的顺序一致

  

六、AngularJS 全局scope与Isolate scope通信

一、scope作用域

1、AngularJS中,子作用域一般都会通过JavaScript原型继承机制继承其父作用域的属性和方法。但有一个例外:在directive中使用scope: { ... },这种方式创建的作用域是一个独立的"Isolate"作用域,它也有父作用域,但父作用域不在其原型链上,不会对父作用域进行原型继承。这种方式定义作用域通常用于构造可复用的directive组件.

2、如果我们在子作用域中访问一个父作用域中定义的属性,JavaScript首先在子作用域中寻找该属性,没找到再从原型链上的父作用域中寻找,如果还没找到会再往上一级原型链的父作用域寻找。在AngularJS中,作用域原型链的顶端是$rootScope,JavaScript寻找到$rootScope为止.

3、scope: { ... } - directive创建一个独立的“Isolate”作用域,没有原型继承。这是创建可复用directive组件的最佳选择。因为它不会直接访问/修改父作用域的属性,不会产生意外的副作用。

二、Isolate scope 引用修饰符

1、 = or =attr “Isolate”作用域的属性与父作用域的属性进行双向绑定,任何一方的修改均影响到对方,这是最常用的方式;

2、 @ or @attr “Isolate”作用域的属性与父作用域的属性进行单向绑定,即“Isolate”作用域只能读取父作用域的值,并且该值永远的String类型;

3、 & or &attr “Isolate”作用域把父作用域的属性包装成一个函数,从而以函数的方式读写父作用域的属性,包装方法是$parse

三、directive 与 controller 数据传递和通信

1、父controller监听全局scope(父scope)变量, 并广播事件给子scope(directive scope,每个directvie都有自己独立的scope作用域)

2、directive 定义本地scope,通过=、@、&(方法)字符显示引用全局scope

3、directive scope(子scope)通过parent[$scope.$parent.xxx]引用全局scope的属性

4、directive监听全局scope变量变化,可以通过$scope.$parent.$watch方法

四、实例讲解

http://www.cnblogs.com/hubcarl/p/4202053.html

七、AngularJS $apply vs $digest

  • $apply会使ng进入$digest cycle, 并从$rootScope开始遍历(深度优先)检查数据变更。
  • $digest仅会检查该scope和它的子scope,当你确定当前操作仅影响它们时,用$digest可以稍微提升性能。
  • 一些不必要的操作,放到$timeout里面延迟执行。
  • 如果不涉及数据变更,还可以加上第三个参数false,避免调用$apply
  • directive中执行的$evalAsync, 会在angular操作DOM之后,浏览器渲染之前执行。
  • controller中执行的$evalAsync, 会在angular操作DOM之前执行,一般不这么用。
  • 而使用$timeout,会在浏览器渲染之后执行。
  • 对时间有要求的,第二个参数可以设置为0。
    $http.get('http://path/to/url').success(function(data){
    $scope.name = data.name;
    $timeout(function(){
    //do sth later, such as log
    }, 0, false);
    });

详细:https://github.com/atian25/blog/issues/5

八、AngularJS Directive 学习 实例

1、restrict 它限制directive为指定的声明方式。如果省略的话,directive将仅仅允许通过属性声明

E - 元素名称: <my-directive></my-directive>

A - 属性名: <div my-directive="exp"></div>

C - class名: <div class="my-directive:exp;"></div>

M - 注释 : <!-- directive: my-directive exp -->

2、dialog实例

<!DOCTYPE html>

<html ng-app="Dialog">

<head>

  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

  <title>directive-dialog</title>

  <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">

  <script src="../../sea-modules/angular/angularjs/1.1.5/angular.js"></script>

</head>

<body>

<div ng-controller="MyCtrl">

  <button ng-click="show=true">show</button>

  <dialog title="Hello }"

          visible="}"

          on-cancel="show=false;"

          on-ok="show=false;methodInParentScope();">

    <!--上面的on-cancel、on-ok,是在directive的isoloate scope中通过&引用的。

    如果表达式中包含函数,那么需要将函数绑定在parent scope(当前是MyCtrl的scope)中-->

    Body goes here: username:} , title:}.

    <ul>

      <!--这里还可以这么玩~names是parent scope的-->

      <li ng-repeat="name in names">}</li>

    </ul>

  </dialog>

</div>

<script type="text/javascript">

  var myModule = angular.module("Dialog", []);

  myModule.controller("MyCtrl", function ($scope) {

    $scope.names = ["name1", "name2", "name3"];

    $scope.show = false;

    $scope.username = "carl";

    $scope.title = "parent title";

    $scope.methodInParentScope = function() {

      alert("scope里面通过&定义的东东,是在父scope中定义!!。。。");

    };

  });

  myModule.directive('dialog', function factory() {

    return {

      priority:100,

      template:['<div ng-show="visible">',

        '    <h3>}</h3>',

        '    <div class="body" ng-transclude></div>',

        '    <div class="footer">',

        '        <button ng-click="onOk()">OK</button>',

        '        <button ng-click="onCancel()">Close</button>',

        '    </div>',

        '</div>'].join(""),

      replace:false,

      transclude: true,

      restrict:'E',

      scope:{

        title:"@",//引用dialog标签title属性的值

        onOk:"&",//以wrapper function形式引用dialog标签的on-ok属性的内容

        onCancel:"&",//以wrapper function形式引用dialog标签的on-cancel属性的内容

        visible:"@"//引用dialog标签visible属性的值

      }

    };

  });

</script>

</body>

</html>

九、AngularJS 注意事项和问题总结(待续)

Beware that using  注意 angular.module('myModule', []) 与 angular.module('myModule') 的使用

angular.module('myModule', []) will create the module myModule and overwrite any existing module namedmyModule.

>>>angular.module('myModule', []) 创建一个新的module,覆盖已经存在的module

Use angular.module('myModule') to retrieve an existing module.

>>>angular.module('myModule') 指向已经存在的module

AngulaJS实战总结, 带你进入AngularJS世界(待续)的更多相关文章

  1. AngulaJS实战

    AngulaJS实战总结, 带你进入AngularJS世界(待续)   使用AngularJS  进行Hybrid App 开发已经有一年多时间了,这里做一个总结. 一.AngularJS 初始化加载 ...

  2. 小丁带你走进git世界一-git简单配置

    小丁带你走进git世界一-git简单配置 1.github的简单配置 配置提交代码的信息,例如是谁提交的代码之类的. git config  –global user.name BattleHeaer ...

  3. 带你走近AngularJS - 基本功能介绍

    带你走近AngularJS系列: 带你走近AngularJS - 基本功能介绍 带你走近AngularJS - 体验指令实例 带你走近AngularJS - 创建自定义指令 ------------- ...

  4. 带你走近AngularJS - 体验指令实例

    带你走近AngularJS系列: 带你走近AngularJS - 基本功能介绍 带你走近AngularJS - 体验指令实例 带你走近AngularJS - 创建自定义指令 ------------- ...

  5. 带你走近AngularJS - 创建自定义指令

    带你走近AngularJS系列: 带你走近AngularJS - 基本功能介绍 带你走近AngularJS - 体验指令实例 带你走近AngularJS - 创建自定义指令 ------------- ...

  6. [Ext JS 4] 实战之 带week(星期)的日期选择控件(三)

    前言 在 [Ext JS 4] 实战之 带week(星期)的日期选择控件(二) 的最后,有提到一个解决方案. 不过这方案有一个条件  ==> “2. 每年的周数从(1-52), 如果超过52 周 ...

  7. 带你走近AngularJS - 创建自己定义指令

    带你走近AngularJS系列: 带你走近AngularJS - 基本功能介绍 带你走近AngularJS - 体验指令实例 带你走近AngularJS - 创建自己定义指令 ------------ ...

  8. 接近带给你AngularJS - 经验说明示例

    接近带给你AngularJS列: 带你走近AngularJS - 基本功能介绍 带你走近AngularJS - 体验指令实例 带你走近AngularJS - 创建自己定义指令 ------------ ...

  9. 带你走近AngularJS 之创建自定义指令

    带你走近AngularJS 之创建自定义指令 为什么使用AngularJS 指令? 使用过 AngularJS 的朋友应该最感兴趣的是它的指令.现今市场上的前端框架也只有AngularJS 拥有自定义 ...

随机推荐

  1. [dpdk] 读官方文档(3)

    续前节, 测试小程序 1. 想编译测试程序首先需要设置两个环境变量,为什么呢,因为测试程序的Makefile里用了... rpm装了打包好的devel包,这个rpm也会自带这两个环境变量.就是说写第三 ...

  2. Bluetooth Low Energy介绍

    目录 1. 介绍 2. 协议栈 3. 实现方案 3.1 硬件实现方案 3.2 软件实现方案 1. 介绍 Bluetooth low energy,也称BLE(低功耗蓝牙),在4.0规范中提出 BLE分 ...

  3. iOS 键盘隐藏

     IOS7 点击空白处隐藏键盘的几种方法   IOS开发中经常要用到输入框,默认情况下点击输入框就会弹出键盘,但是必须要实现输入框return的委托方法才能取消键盘的显示,对于用户体验来说很不友好,我 ...

  4. java实验一实验报告

    Java实验报告一:Java开发环境的熟悉                                                                               ...

  5. XCode中的单元测试:编写测试类和方法(内容意译自苹果官方文档)

    当你在工程中通过测试导航栏添加了一个测试target之后, xcode会在测试导航栏中显示该target所属的测试类和方法. 这一章演示了怎么创建测试类,以及如何编写测试方法. 测试targets, ...

  6. php--列表展示(小实训一月考)

    效果图:

  7. 帝国CMS备忘

    一. 2级导航: 类似下图这种导航: 实现方式如: 1. 定义一个标签模板,记住ID,具体内容如: 页面模板内容: <li><a href=”[!—bclassurl—]”>[ ...

  8. 雾里看花终隔一层——探析package和import

    package是什么 package好比java用来组织文件的一种虚拟文件系统.package把源代码.java文件,.class文件和其他文件有条理的进行一个组织,以供java来使用. 源代码的要求 ...

  9. for循环数据节点

    1.需要实现的功能,动态填充多条银行卡信息 2.dom结构 3.数据节点 4.实现方式 //获取银行卡基本信息 CmnAjax.PostData("Handler/Users/Users.a ...

  10. ArcGIS中添加进自定义的ttf字符标记符号

    原文:ArcGIS中添加进自定义的ttf字符标记符号 ArcGIS系统中的样式可能不能满足实际生产需要,为了实现快速制图,可自定义一些样式,以便重复利用. 1.   制作的符号库 使用 FontCre ...