作用域、控制器、模块和服务是AngularJS的重要对象
1. 作用域:
* 一个js实例对象, ng-app指令默认会创建一个根作用域对象($rootScope)
* 它的属性和方法与页面中的指令或表达式是关联的
2. 控制器:
* 用来控制AngularJS应用数据的实例对象
* ng-controller : 指定控制器构造函数, Angular会自动new此函数创建控制器对象,
产生新的作用域对象
* 同时Angular还有创建一个新的域对象$scope, 它是$rootScope的子对象
* 在控制器函数中声明$scope形参, Angular会自动将$scope传入
问题: angular是如何解析ng-controller='XxxController'指令的?
1). 创建一个新的scope对象, 且它继承于$rootScope
2). 调用指令所指向的函数: new XxxController(scope对象)
3.模块
大部分应用都有一个主方法用来实例化、组织、启动应用。AngularJS应用没有主方法,而是使用模块来声明应用应该如何启动。这种方式有以下几个优点:
1.启动过程是声明式的,所以更容易懂。
2.在单元测试是不需要加载全部模块的,因此这种方式有助于写单元测试。
3.可以在特定情况的测试中增加额外的模块,这些模块能更改配置,能帮助进行端对端的测试。
4.第三方代码可以打包成可重用的模块。
5.模块可以以任何先后或者并行的顺序加载(因为模块的执行本身是延迟的)。
<body ng-app="myApp">
<div ng-controller="MyCtrl1">
<input type="text" ng-model="empName">
<p>员工名: {{empName}}</p>
</div>
<div ng-controller="MyCtrl2">
<input type="text" ng-model="empName">
<p>员工名2: {{empName}}</p>
</div>
<script type="text/javascript" src="../../js/angular-1.2.29/angular.js"></script>
<script type="text/javascript">
console.log(angular, typeof angular); // 全局变量
/*
//创建当前应用的模块对象
var module = angular.module('myApp', []);
//定义控制器
module.controller('MyCtrl1', function ($scope) {
$scope.empName = 'Tom';
})
module.controller('MyCtrl2', function ($scope) {
$scope.empName = 'Jack';
})
*/
//方法链调用
/*angular.module('myApp', [])
.controller('MyCtrl1', function ($scope) {
$scope.empName = 'Tom2';
})
.controller('MyCtrl2', function ($scope) {
$scope.empName = 'Jack2';
})*/
/*
上面写法的问题:
1. 只能写指定的变量名$scope
2. 如果压缩后, 不能正常运行
*/
angular.module('myApp', [])
.controller('MyCtrl1', ['$scope', function (scope) {
scope.empName = 'Tom3';
}])
.controller('MyCtrl2', ['$scope', function (s) {
s.empName = 'Jack3';
}])
</script>
</body>
上面代码,我们是通过在<body ng-app="myApp">中指定控制器,ctrl1、ctrl2,来实现使用myApp这个模块启动应用的。
相关知识:
属性是什么:属性是一个变量,用来表示一个对象的特征,如颜色、大小、重量等。属性有属性名和属性值。
方法是什么:方法是一个函数,用来表示对象的操作,如奔跑、呼吸、跳跃等。相当于特殊的属性,当属性值是函数的时候就是方法。
在JavaScript中,可以使用“ . ”和“ [ ] ”来访问对象的属性。
这篇博客介绍js对象获取属性的两种方法的对比,说的挺好。http://www.jb51.net/article/74898.htm
4.服务
4.1什么是服务?
具有特定功能的对象(object对象、函数,数组,基本类型)
4.2怎么理解服务?
作者:徐海峰 链接:https://www.zhihu.com/question/23278281/answer/24489440 来源:知乎
AngularJS中的服务其实就是提供一种方式抽取共用类库
比如说一些工具类方法,我们传统的做法就是自己写个 utility 类,把相关的工具方法填充到utility里面去,最后把utility类放到一个全局的变量中,这样任何地方都可以调用utility的方法。
如果用AngularJS的service,你按照他的规则创建一个 utility 服务,然后在任何地方都可以通过依赖注入调用utility里面的方法。
4.3服务又分为内置服务和自定义服务
* 内置服务
* 都以$开头
* 引入内置服务: 声明式依赖注入(定义形参), 你不使用它就存在了
* 常用的几个:
* $rootScope
* $scope
* $timeout
* $interval
* 脏数据检查:
* 当angular定义的函数执行完后, 会对scope内的属性进行检查, 如果发现有改变更新界面
* 在非angular定义的回调函数执行完后, 不会进行脏数据检查 --->即使更新了scope页面不会同步更新
* 页面如何能自动更新的?
* 在内置的一些函数执行完后,angular会进行脏数据检查的操作
* controller, $timeout()中的回调函数, $interval()中的回调函数
* 如果我们在setTimeout()的回调函数中更新scope,是不会进行脏数据检查的,页面不可能更新
* 自定义服务
* 使用module对象来定义服务
* 定义的常用方法:
* factory('fService', function(){return 服务}) : 可以定义任意类型的服务
* service('sService', function(){}) :只能定义object类型对象
*factory()
factory('服务名',function(){
return 服务对象; //可以是任意类型
})
* 如何引入: 声明式依赖注入
这篇博客讲了五种自定义服务方法(constant、value、service、factory、provider)的区别:https://segmentfault.com/a/1190000003096933
angular.module('myApp',[])
.factory('personsStorage',function () {//产生服务对象的工厂函数
var key = 'persons_key';
return {
readPersons : function () {
//如果没有就返回[]
return JSON.parse(sessionStorage.getItem(key) || '[]');
},
savePersons : function (persons) {
//转成JSON再保存
sessionStorage.setItem(key,JSON.stringify(persons))
},
removePersons : function () {
sessionStorage.removeItem(key);
}
};
})
.service('personsStorage2',function () {//服务对象的构造函数,里边的内容必须是对象
var key = 'persons_key';
this. readPersons = function () {
//如果没有就返回[]
return JSON.parse(sessionStorage.getItem(key) || '[]');
};
this.savePersons = function (persons) {
//转成JSON再保存
sessionStorage.setItem(key,JSON.stringify(persons))
};
this.removePersons = function () {
sessionStorage.removeItem(key);
};
})
.controller('MyController',function ($scope,personsStorage,personsStorage2) {
var persons = [
{name : 'Tom',age :12},
{name : 'Tom2',age :13},
{name : 'Tom3',age :14}
];
$scope.save = function () {
personsStorage2.savePersons(persons);
}
$scope.read = function () {
$scope.persons = personsStorage2.readPersons();
}
$scope.remove = function () {
personsStorage2.removePersons();
}
});