AngularJS学习笔记
2017-04-24 22:20
453 查看
AngularJS在加载启动时,会做3件事情:
1.依赖注入
2.创建 root scope作为整个模型的上下文
3.从ngApp开始编译DOM,处理后续的指令和绑定
当它启动后,它会等待浏览器的输入事件(鼠标、HTTP请求等),若输入事件改变了model,那么AngularJS会通过更新绑定,将model的改变反应到view上。
AngularJS中指令都是带有短划线(-)的,自定义的属性都是驼峰命名的
1.ng-app:
2.ng-controller:定义了一个叫做PhoneListController的控制器,并且向module(phonecatApp)注册。model模型(手机的数据)在controller中,model由controller实例化,controller函数就是一个简单的构造函数。参数scope在该controller范围内都是有效的。scope是template、model、controller之间的联系纽带(template可以理解为是view中的一部分,包括数据绑定、展示逻辑)。
我们在scope下分配参数,可以在其他页面(使用相同的controller)使用该参数,这样交互就会显得比较灵活。但是这种方法只适用于小型的系统,若在大型系统上,紧耦合就会成为一个问题。
3.ng-repeat:
PS:不要搞错module模块和model模型,MVC里的M是指model。
1.如果我们要复用template和controller,在上面的例子中,我们需要把他们都复制到复用的地方,这样容易出错。
2.我们把变量都赋值到scope下面,这样会造成混乱。
我们可以在html中使用标签
避免直接使用scope,这是一条最佳实践。
1.新建一个
2.在新的应用newApp中,添加phonecatApp依赖
AngularJS内置的服务都是带有
JS在发布前都会经过压缩混淆,混淆其中有个步骤就是替换局部变量,如果
1.创建
2.使用内联的注解
在controller后面跟一组字符串。
2.1使用内联的注解
当我们使用方法2时,一般都是把构造函数也内联进来。(在刚接触AngularJS时,经常看到这种形式的内联,当时就感觉JS代码一层套一层好复杂,一句话好长,而且对
对本例代码使用2.1的注解形式:
1.加载定义的module
2.注册所有在module后面定义的Providers
3.当要使用服务了,这些服务和他们的依赖,就会通过他们的Providers被传入注射依赖函数
Providers是一个对象,这个对象可以创建相应的服务。
在url上加前缀
顶层模块phonecatApp和子模块phoneDetail都包含ngRoute服务,如果我们把phoneDetail中的ngRoute去掉,程序也是可以工作的,但不建议这么做,因为这样会破坏模块化,子模块不应该依赖由父模块继承下来的服务。假如phoneDetail模块被放到其他地方,这个顶层模块没有ngRoute,那么phoneDetail模块就不能正常工作。我们不用担心多个模块包含了多份一样的服务会造成多余的浪费,AngularJS只会加载一份服务。
1.依赖注入
2.创建 root scope作为整个模型的上下文
3.从ngApp开始编译DOM,处理后续的指令和绑定
当它启动后,它会等待浏览器的输入事件(鼠标、HTTP请求等),若输入事件改变了model,那么AngularJS会通过更新绑定,将model的改变反应到view上。
AngularJS中指令都是带有短划线(-)的,自定义的属性都是驼峰命名的
1.ng-app:
2.ng-controller:定义了一个叫做PhoneListController的控制器,并且向module(phonecatApp)注册。model模型(手机的数据)在controller中,model由controller实例化,controller函数就是一个简单的构造函数。参数scope在该controller范围内都是有效的。scope是template、model、controller之间的联系纽带(template可以理解为是view中的一部分,包括数据绑定、展示逻辑)。
我们在scope下分配参数,可以在其他页面(使用相同的controller)使用该参数,这样交互就会显得比较灵活。但是这种方法只适用于小型的系统,若在大型系统上,紧耦合就会成为一个问题。
3.ng-repeat:
PS:不要搞错module模块和model模型,MVC里的M是指model。
// Define the `phonecatApp` module var phonecatApp = angular.module('phonecatApp', []); // Define the `PhoneListController` controller on the `phonecatApp` module phonecatApp.controller('PhoneListController', function PhoneListController($scope) { $scope.phones = [ { name: 'Motorola XOOM™ with Wi-Fi', snippet: 'The Next, Next Generation tablet.' }, { name: 'MOTOROLA XOOM™', snippet: 'The Next, Next Generation tablet.' } ]; });
component
相对于上述例子,还有一些地方我们可以改进:1.如果我们要复用template和controller,在上面的例子中,我们需要把他们都复制到复用的地方,这样容易出错。
2.我们把变量都赋值到scope下面,这样会造成混乱。
//组件greetUser向模块myAPP注册 angular. module('myApp'). component('greetUser', { template: 'Hello, {{$ctrl.user}}!', controller: function GreetUserController() { this.user = 'world'; } });
我们可以在html中使用标签
<greet-user></greet-user>,然后AngularJS会用template去替换它。
$ctrl在默认情况下,代表着controller。我们在controller的构造函数中用this代替了在scope下赋值。标签
<greet-user></greet-user>可以自任何地方使用,也实现了最大限度的解耦。我们也不用担心component会在其他地方被修改,因为template、controller都在component里面。
避免直接使用scope,这是一条最佳实践。
文件组织的最佳实践
1.一个特性一个文件
不要把controller都放在一个js文件里,不要把component都放在一个js文件里。比如上述的componentgreetUser,需要放在greetUser.component.js里,那么在这js文件里就不要放其他东西了。
2.按特性组织
按照1中的方法,一个文件放置一个特性,那么在app/目录下会产生许多文件,我们需要将这些文件按特性组织成文件夹。如果在许多的地方都会用到同一个特性,那么我们就把这个特性文件夹放到
aap/core/里面。
app/ phone-list/ phone-list.component.js phone-list.component.spec.js(test) core/ feature1/ xxx.js xxx.spec.js app.js
// phone-list.component.js // Register `phoneList` component to module 'phonecatApp' angular. module('phonecatApp'). component('phoneList',...)
// app.js // Define the `phonecatApp` module // 模块phonecatApp没有依赖其他模块,只有它本身 angular.module('phonecatApp', []);
3.模块化
如果现在有其他应用要用到phone-list,我们不需要重复发明轮子,只需要把目录phone-list/复制到新应用下。但是我们发现,原来在
phone-list/中,component
phoneList是向module
phonecatApp注册的,在新的应用中,应用名就不叫
phonecatApp了,这时我们需要把
phonecatApp都改为当前的应用名。显然,这样的改动容易出错且重复劳动。我们有更好的方法去做这件事。引用一句最近在《Head first 设计模式》上看到的话,对改动关闭,对扩展开放,我们不要去改动已有代码,这样可能在修改一个bug的同时代入另外一个bug,我们应该是封装、抽象、扩展我们已有的代码。
1.新建一个
phone-list.module.js文件,把component提高到module层次。
2.在新的应用newApp中,添加phonecatApp依赖
app/ phone-list/ phone-list.module.js phone-list.component.js phone-list.component.spec.js core/ feature1/ xxx.js xxx.spec.js app.js
//app/phone-list/phone-list.module.js: // Define the `phonecatApp` module angular.module('phonecatApp', []);
// phone-list.component.js // Register `phoneList` component to module 'phonecatApp' angular. module('phonecatApp'). component('phoneList',{ template: '<ul>' + '<li ng-repeat="phone in $ctrl.phones">' + '<span>{{phone.name}}</span>' + '<p>{{phone.snippet}}</p>' + '</li>' + '</ul>', ... })
// app.js // Define the `newApp` module angular.module('newApp', [ // ...which depends on the `phonecatApp` module 'phonecatApp' ]);
4.使用外部模板
在3中,component里面的template是内嵌式的html,这样不易于维护和模块化,我们把内嵌式的html改为外部的html。这里有一个点需要注意:当AngularJS解析到templateUrl时,会发起一个HTTP请求,虽然AngularJS使用了延时加载和缓存技术,但随着外部模板变多,HTTP请求也不可避免的变多。详细可以参阅$templateRequest和
$templateCache这两项服务。
// phone-list.component.js angular. module('phoneList'). component('phoneList', { // Note: The URL is relative to our `index.html` file templateUrl: 'phone-list/phone-list.template.html', controller: ... });
// phone-list.template.html <ul> <li ng-repeat="phone in $ctrl.phones"> <span>{{phone.name}}</span> <p>{{phone.snippet}}</p> </li> </ul>
//最终的目录 app/ phone-list/ phone-list.component.js phone-list.component.spec.js phone-list.module.js phone-list.template.html app.css app.js index.html
第六节.双向数据绑定
双向数据绑定是指view和model在两个方向上都绑定住了。如果我们在浏览器上改变view,那么就会反应到model里面,进而改变model。如果我们在代码里面改变model,那么就会向外反应到view上。第七节.依赖注入
使用内置的http服务为例子。$http服务会让AngularJS在客户端发起一个http请求,在下面的例子中,http去请求一个json文件,路径是相对于index.html来说的。服务的名字需要作为参数传入到controller的构造函数中。服务的名字很重要,不能写错,注入器就是依靠名字去寻找依赖的。注入器在加载一个服务时,会分析这个服务会依赖其他哪几个服务,然后依次去加载服务。
angular. module('phoneList'). component('phoneList', { templateUrl: 'phone-list/phone-list.template.html', controller: function PhoneListController($http) { var self = this;//this对象在闭包中会发生变化,在这里将this保存成一个变量,该变量在闭包中的含义不会发生变化 self.orderProp = 'age'; //phone的数据不像之前被写死,而是由http请求去json文件里面读取 $http.get('phones/phones.json').then(function(response) { self.phones = response.data; }); } });
AngularJS内置的服务都是带有
$前缀的,如果我们要定义自己的服务,就不要带
$前缀。而且我们会看到在Scope下面,有些变量是带有
$$前缀的,那说明这个变量是私有的,虽然我们还是可以去访问,但不建议这么做。
JS在发布前都会经过压缩混淆,混淆其中有个步骤就是替换局部变量,如果
$http这个变量被替换了,AngularJS就识别不出来使用了内置的http服务,所以针对混淆,代码要换个结构。有以下两种方法:
1.创建
$inject属性
$inject后面跟一组字符串,字符串就不会被js混淆替换掉,这些字符串就是要依赖的服务。
function PhoneListController($http) {...} PhoneListController.$inject = ['$http']; ... .component('phoneList', {..., controller: PhoneListController});
2.使用内联的注解
在controller后面跟一组字符串。
function PhoneListController($http) {...} ... .component('phoneList', {..., controller: ['$http', PhoneListController]});
2.1使用内联的注解
当我们使用方法2时,一般都是把构造函数也内联进来。(在刚接触AngularJS时,经常看到这种形式的内联,当时就感觉JS代码一层套一层好复杂,一句话好长,而且对
$http出现2次感到不解)
.component('phoneList', {..., controller: ['$http', function PhoneListController($http) {...}]});
对本例代码使用2.1的注解形式:
//app/phone-list/phone-list.component.js angular. module('phoneList'). component('phoneList', { templateUrl: 'phone-list/phone-list.template.html', controller: ['$http', function PhoneListController($http) { var self = this; self.orderProp = 'age'; $http.get('phones/phones.json').then(function(response) { self.phones = response.data; }); } ] });
第九节.路由和多视图
依赖注射器做以下3件事:1.加载定义的module
2.注册所有在module后面定义的Providers
3.当要使用服务了,这些服务和他们的依赖,就会通过他们的Providers被传入注射依赖函数
Providers是一个对象,这个对象可以创建相应的服务。
在url上加前缀
!是一个最佳实践,如url
http://127.0.0.1:8000/#!/phones
关于自模块的依赖:
// app/app.js angular.module('phonecatApp', [ 'ngRoute', 'phoneDetail', 'phoneList' ]);
// app/phone-detail/phone-detail-module.js angular.module('phoneDetail', [ 'ngRoute' ]);
顶层模块phonecatApp和子模块phoneDetail都包含ngRoute服务,如果我们把phoneDetail中的ngRoute去掉,程序也是可以工作的,但不建议这么做,因为这样会破坏模块化,子模块不应该依赖由父模块继承下来的服务。假如phoneDetail模块被放到其他地方,这个顶层模块没有ngRoute,那么phoneDetail模块就不能正常工作。我们不用担心多个模块包含了多份一样的服务会造成多余的浪费,AngularJS只会加载一份服务。
相关文章推荐
- AngularJs学习笔记--IE Compatibility 兼容老版本IE
- AngularJs学习笔记--directive
- AngularJs学习笔记--Guide教程系列文章索引
- 蛙蛙推荐:AngularJS学习笔记
- AngularJs学习笔记--concepts(概念)
- AngularJs学习笔记--html compiler
- AngularJs学习笔记--bootstrap
- AngularJs学习笔记--unit-testing
- AngularJS学习笔记3——AngularJS的工作原理
- AngularJs学习笔记--Creating Services
- AngularJs学习笔记--I18n/L10n
- AngularJs学习笔记--Scope
- AngularJs学习笔记--Modules
- AngularJs学习笔记--Injecting Services Into Controllers
- AngularJs学习笔记--E2E Testing
- AngularJs学习笔记--Forms
- AngularJs学习笔记--Dependency Injection(DI,依赖注入)
- AngularJs学习笔记--concepts(概念)
- AngularJS学习笔记1——什么是AngularJS?
- AngularJs学习笔记--bootstrap