框架:优秀的可以重复使用的代码,单独提取并封装,提高代码的服用了、开发速度,并保证良好的浏览器的兼容性。
angularJS、phoneGap、Ionic、ZeptoJS、React。。。
判断框架:①它适用的场景 ②如何使用 ③遇到了问题怎么解决(维基百科、官网、论坛(stackoverflow))
一、常用的设计原则和设计模式
1、设计原则(明确)
① YANGI(You aren‘t gonna need it) 不写不需要的代码
②KISS(Keep it simple and stupid) 代码越简单越好
③DRY(Don‘t Repeat Yourself)封装代码
④高内聚低耦合
内聚:一个模块内部的不同部分之间的关系
耦合:不同模块/组件的关系
⑤SRP(single responsibility principle) 单一责任原则
⑥OCP(open closed principle) 开闭原则
对扩展开放 对修改关闭
⑦LCP(least knownledge principle) 最少知识法则
2、设计模式(23种 了解)
总体来说设计模式分为三大类:
①创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
②结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
③行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
经常用到的设计模式:
工厂方法模式、单例模式、适配器模式、解释器模式、观察者模式
MVC、MVVM、MVP。。。--》终极目标:模块化和复用
MVC:
Model(模型数据)、View(视图)、Controller(控制器)
遥控器--》控制器:数据的增删改查的操作
电视 --》View:展示数据
光缆 --》Model:模型数据
why MVC?
解耦(降低代码的耦合度)、职责的切分。。。。
工作原理:当对视图操作的时候,触发控制器中的一些方法,在这些方法中对于数据的增删改查的操作,借助一些绑定显示,更新到视图。
二、认识AngularJS
1、什么是AngularJS
ng是一个由Google维护的开源的框架,实现单页面应用程序,适用于数据操作比较频繁的场景
2、为什么AngularJS
四大特征:
①采用了MVC的设计模式
②双向数据绑定
③依赖注入
④模块化设计
3、怎么使用?
引入对应的js文件。
3.1 表达式
语法:{{表达式}}
作用:将表达式的结果输出到调用该表达式的元素的innerHTML中
练习:新建一个html文件,在文件中,通过双花括号语法执行算术运算、比较运算、逻辑运算、三目运算。
3.2 指令
ngApp指令:①指定angularJS的作用范围②自动载入并启动ng应用
ngInit指令:初始化一些变量(对象、数组。。。),注意:不需要写上var关键字
语法:<ANY ng-init=""></ANY>
练习:ngInit指令创建一个对象数组(学生数组),模拟4个对象,每个对象包含name、sex、score;将对象数组输出到一个table中。
步骤:
①引入js文件,指定ngApp指令
②通过ngInit初始化数据
③将数据展示在table中。
ng中的指令:是由AngularJS提供的,可以将指令用在HTML中作为扩展属性、扩展标签
扩展属性用法:<ANY ng-xx=""></ANY>
扩展标签用法:<ngView></ngView>
ngApp/ngInit
注意事项:ngInit来初始化变量的时候,如果需要初始化多个变量,只需要通过‘;’来隔开
<span ng-init="name=‘lucy‘;age=20">{{name}}</span>
ngApp指令ng应用的作用范围,如果ngApp调用了多次,只有第一次是生效的。
一、自定义指令
语法:
var app = angular.module(‘myModule‘,[‘ng‘]);
app.directive(name,fn);
自定义指令:
restrict:‘EACM‘
E-->Element 元素
A-->Attribute 属性
C-->Class
M-->Comment 注释(在指令中添加一个属性:replace:true)
新指令的命名:
①驼峰式
②前缀一般是公司或者项目的简写,后缀一般是指令的作用
③使用指令: tsHello--->ts-hello
在第二个参数 指定一个方法,在方法中返回一个对象设置指令。对象中template、restrict、replace、scope。。。
总结:如果要参数的传递,需要在创建指令的时候,加上scope,同时指定对应的属性的名称(testName),在使用指令的时候,需要加上对应的属性(test-name=‘‘)
练习:创建自定义的指令 tsDirective,传入ts-name="Hello Directive",调用指令(作为元素来使用)显示出来。
二、双向数据绑定
1、方向1的绑定(Model数据 绑定到View)
实现方法:{{name}}、常用指令(ngRepeat/ngBind/ngIf...)
相比DOM操作:先去查找元素,再去设置元素,只需要把model数据绑定视图上,数据改,视图就会更新。
2、方向2的绑定(将View数据绑定到Model数据)
实现方法只有一种方式: ng-model
<input type=‘text‘ ng-model=‘myText‘/>
$scope.$watch(‘模型变量名‘,function(){})
练习:
留言本:多行文本输入框textarea、
选择城市:下拉菜单select、
是否同意:复选框 checkbox
三、过滤器
四、常用函数
一、自定义指令
语法:
var app = angular.module(‘myModule‘,[‘ng‘]);
app.directive(name,fn);
自定义指令:
restrict:‘EACM‘
E-->Element 元素
A-->Attribute 属性
C-->Class
M-->Comment 注释(在指令中添加一个属性:replace:true)
新指令的命名:
①驼峰式
②前缀一般是公司或者项目的简写,后缀一般是指令的作用
③使用指令: tsHello--->ts-hello
在第二个参数 指定一个方法,在方法中返回一个对象设置指令。对象中template、restrict、replace、scope。。。
总结:如果要参数的传递,需要在创建指令的时候,加上scope,同时指定对应的属性的名称(testName),在使用指令的时候,需要加上对应的属性(test-name=‘‘)
练习:创建自定义的指令 tsDirective,传入ts-name="Hello Directive",调用指令(作为元素来使用)显示出来。
二、双向数据绑定
1、方向1的绑定(Model数据 绑定到View)
实现方法:{{name}}、常用指令(ngRepeat/ngBind/ngIf...)
相比DOM操作:先去查找元素,再去设置元素,只需要把model数据绑定视图上,数据改,视图就会更新。
2、方向2的绑定(将View数据绑定到Model数据)
实现方法只有一种方式: ng-model
<input type=‘text‘ ng-model=‘myText‘/>
$scope.$watch(‘模型变量名‘,function(){})
练习:
留言本:多行文本输入框textarea、
选择城市:下拉菜单select、
是否同意:复选框 checkbox
三、过滤器
过滤器是用在表达式中,实现对表达式结果的筛选、过滤、格式化,达到更好的表现效果
语法:|--》管道
{{表达式 | 过滤器1:‘name‘ | 过滤器2 }}
currency 货币样式的过滤器
date 日期
uppercase
lowecase 大小写的转换
orderBy 升序或者降序 orderBy:‘age‘:true
limitTo 限定显示的数量
number 限制显示小数点后几位
练习:过滤器,模拟一个list=[{name,age,score},{}],、
①按照age升序,②按照score降序并只显示前三名
四、常用函数
forEach
uppercase/lowercase
toJson/fromJson
序列化:将一个json对象转换为json格式的字符串
反序列化:将一个json格式的字符串 转换为json格式的对象
五、服务
在ng中 服务 是 一种单例对象,所谓单例,服务在每一个应用中只会被实例化一次。
功能:为应用提供数据和对象
两大类:①内置的服务 ②自定义服务
1、内置的服务的使用方法
如果在控制器中,使用ng中内置的服务,需要在控制器的回调函数中
①将对应的服务给注入进来
②使用服务所提供的数据和对象
app.controller(‘myCtrl‘,function($scope,$location){
var url = $location.absUrl();
});
2、控制器和作用范围
$scope与$rootScope:
$scope是$rootScope的子作用域控制对象,$rootScope的id为1,其他的为2,3....
不同的控制器之间,所对应的作用域控制对象($scope),之间是相互隔离的,如果要共享数据,怎么办?
借助$rootScope这个根作用域控制对象来实现。
如果父作用域对象想要调用子作用域对象的变量或者方法,ng提供了2个方法:
①$broadcast 将事件从父亲传递给子级
$scope.$broadcast(eventName,data);
②$emit 将事件从子级传递给父亲
$scope.$emit(eventName,data);
接收:
$scope.$on(eventName,function(event,data){
})
每日一练:全选
双向数据绑定
ngChecked/ngClick/ngModel/ngChange
分析:
模型数据是一个对象数组
步骤:
①ui搞定
②部分选中
③全部选中
一、ng内置的服务($http,$interval,$timeout...)
①双向数据绑定的工作原理
<p>{{num}}</p>===>ng框架自动添加一个监听(watch),和$scope.$watch是一样的,只要是数据发生了变化,视图就会更新。???
如何知道数据是否发生了变化?
ng会周期性的运行一个函数来检查$scope的模型数据是否发生变化,称之为$digest===>$scope.$digest()
什么时候才会调用$digest()?
ng指令,很少直接手工调用$digest(),都是$scope.$apply();==>$rootScope.$digest()
setInterval是原生js的功能,本身就是一个循环,需要我们手工调用$scope.
②$interval $timeout
var t = $interval(function(){},100);
$timeout(function(){},100);
$interval.cancel(t);
定时器练习:
使用周期性定时器来实现一个图片轮播,同时实现一个自增的计数器,当计数器大于30时自动停止。
③$http
AJAX调用:$http服务向服务器发起AJAX请求,异步的获取服务器端返回的数据,声明为模型数据,在视图中展现出来。
$http.get(‘url‘).success(function(data){....});
$http.post(‘url‘,data).success(function(data){..})
如果要发起post请求,必须设置头信息,设置的方式:
$http.defaults.headers.post = {‘Content-Type‘:‘application/x-www-form-urlencoded‘};
练习:$http发起get请求,编写一个php文件,返回json数组。
显示在table中。
分析:apache服务跑起来,将工程放在c:\xampp\htdocs的目录中。
第一步:编写php文件,在浏览器中去访问该文件能否拿到数据
第二步:$http发起get请求,拿到数据
第三步:将数据显示在table中。
二、自定义服务
无论是哪种方式创建的服务,和ng内置的服务使用的方式都是一致:注入进来,直接拿来用
1、factory方法
app.factory(‘服务名称‘,function(){
return {
}
})
2、service方法
app.service(‘服务名称‘,function(){
})
3、constant、value
创建的服务返回是变量
app.constant(‘服务名称‘,value) ==> 创建配置数据
app.value(‘服务名称‘,value) ==》创建对象
常量服务如果注入到控制器之后,可以通过angular.extend方法进行重置
练习:使用service方法 创建一个服务,在服务中有两个方法,方法1中,启动一个定时器 每隔1s打印一句话,方法2:结束定时器;放置2个按钮,点击时分别调用服务中的方法1、方法2,
三、依赖注入
1、文件压缩
使用YUICompresspor来完成文件的压缩,使用方式有2种:
①直接通过命令行
②借助webStorm来配置
File--》Settings-->tools-->file watchers--》点击右上角的+号--》选中YUICOMPRESSOR-JS,设置program为jar包。
文件压缩的作用:
①删除所有的注释
②删除空白、没有语义的字符
③简化变量名、函数名、形参名--》混淆
2、依赖注入
每个angularjs的应用,注入器负责查找和创建依赖的服务,注入器的本质是服务的定位器,快速定位到应用需要注入的各种服务,在定位服务的过程当中,需要提供注入的标记,根据标记的不同,划分为3大类:
①推断式依赖注入(猜测)
这种方法不需要关心注入服务的顺序,ng会自动处理,根据参数列表注入服务,如果参数一旦经过混淆或者压缩,有问题。
只能处理原始的代码
②标记式依赖注入
直接调用$inject属性来完成标记式的注入声明,该属性是一个字符型的数组,由于它是数组,所以有引入的先后顺序的。
③行内式依赖注入(内联)
在构建一个ng对象时,允许开发人员将一个字符型数组作为对象的参数,而不仅仅是一个函数;在这个数组中,除最后一个元素必须是函数体外,其余都是注入的服务名称,而且顺序保持一致。
建议:使用第三种依赖注入的方式:行内式依赖注入。
练习:要求采用行内式依赖注入,创建一个服务,服务中有一个方法实现求和 add:function(arg1,arg2)
视图:两个input标签,一个按钮(调用服务的add方法将求和的结果弹窗显示出来)。
3、注入器($injector)
定位和查找服务的。
has --》查找服务是否存在
get --》得到服务的实例
练习:在案例基础之上,放置一个按钮,点击按钮时,通过get拿到实例并调用print方法(angular.injector-->$injector 行内式依赖注入)
每日一练:
实现一个购物车:要求从php服务器获取初始化的数据,通过$http.
ng四大特征:
①采用了MVC的设计模式
②双向数据绑定(view和model)
③依赖注入
④模块化设计
一、如何自定义模块并进行调用??
自定义模块:angular.module()
模块之间如何相互之间的调用: angular.module(‘myApp02‘,[‘ng‘,‘myApp01‘]);
模块化好处:体现“高内聚低耦合”的设计原则,提高代码的复用率,降低测试难度。
模块分类:
①ng官方提供的模块
ng\ngAnimate\ngRoute\ngTouch...
②用户自定义的模块
angular.module();
二、ng包含哪些模块
一个angularJS的模块可以包含哪些组件??
①controller:维护模型数据
②directive:用在view中 输出/绑定Model数据
③function:forEach\toJson\fromJson
④filter:结果的筛选、过滤、格式化
⑤service:提供变量或者方法的服务
。。。
三、SPA应用以及通过ngRoute来实现的方式
单页面应用的工作原理:
①url
http://127.0.0.1/index.html#/路由地址
②浏览器请求index.html,解析路由地址
③查找路由词典,#/start ==>tpl/start.html
④获取当前路由地址 对应的真实模板的地址 start.html
⑤发起ajax请求,获取目标模板页面,将服务器返回的代码片段,插入到当前的DOM树,实现局部刷新
使用ngRoute模块来实现SPA应用的基本步骤:
①创建完整的HTML页面 index.html,引入angular.js,angular-route.js
②创建自定义的模块,指定依赖于ng\ngRoute
③指定容器,盛放代码片段 ngView
④创建模板页面
⑤配置路由词典
$routeProvider.when(‘/start‘,{
templateUrl:‘tpl/start.html‘,
controller:‘startCtrl‘})
⑥测试在地址栏中 输入不同的路由地址的时候,能否将代码片段加载进来。
四、代码片段之间的跳转
模板页面之间 执行跳转的3种方式:
①直接修改地址栏中的url
②使用超链接 <a href=‘#/路由地址‘></a>
③$location.path(‘/路由地址‘)
如果有多个代码片段,都需要通过js的方式来跳转,为每个代码片段去创建控制器 去定义jump方法,这个是不合理的,可以这么处理:借助父控制器定义方法,然后让子控制器去调用。
配置代码片段的控制器的方式:
①ng-controller
②配置路由词典设置
$routeProvider.when(‘/myLogin‘,{
templateUrl:‘tpl/login.html‘,
controller:‘loginCtrl‘
});
练习:使用ngRoute来实现一个SPA应用。
创建一个完整的html--》index.html;创建2个代码片段 --》start.html register.html
start.html --> 点击按钮跳转到register,
register.html -->a 跳转到start.html
从register跳转到start
五、代码片段进行传参
使用ngRoute进行参数的传递:
①明确发送方和接收方
发送方:register
接收方:start
②配置接收方的路由以及接受参数
.when(‘/myStart‘,{
templateUrl:‘tpl/start.html‘
})
.when(‘/myStart/:id‘,{
templateUrl:‘tpl/start.html‘
})
如果接受id,
借助ngRoute服务
$routeParams.id
③发送参数
<a href=‘#/myStart/123‘></a>
$location.path(‘/myStart/123‘)
练习:实现SPA应用
完整:manager.html
代码片段:check.html pay.html send.html
要求:
①能够实现不同页面的跳转
②check.html-->超链接跳转到pay.html,传入price,
pay.html接受参数并显示在页面中
pay.html--》按钮 点击跳转到send.html
send.html-->超链接跳转到check.html
六、动态引入页头页尾
ngInclude:
<ANY ng-include="‘tpl/include/header.html‘"></ANY>
七、其他模块
ngAnimate 支持js动画和css动画
①通过script 引入angular-animate.js到工程中
②指定自定义的模块,要依赖于ngAnimate
③设置cssngAnimate模块为ngView添加ng-leave和ng-leave-active、ng-enter和ng-enter-active.
八、表单
在ng中,专门针对表单和表单中的控件,提供了一些属性,用于验证控件值的状态。
$pristine 未输入过
$dirty 已输入过
$valid 验证通过
$invalid 验证未通过
$error 验证时的错误信息
ng四大特征:
①采用了MVC的设计模式
②双向数据绑定(view和model)
③依赖注入
④模块化设计
一、如何自定义模块并进行调用??
自定义模块:angular.module()
模块之间如何相互之间的调用: angular.module(‘myApp02‘,[‘ng‘,‘myApp01‘]);
模块化好处:体现“高内聚低耦合”的设计原则,提高代码的复用率,降低测试难度。
模块分类:
①ng官方提供的模块
ng\ngAnimate\ngRoute\ngTouch...
②用户自定义的模块
angular.module();
一个angularJS的模块可以包含哪些组件??
①controller:维护模型数据
②directive:用在view中 输出/绑定Model数据
③function:forEach\toJson\fromJson
④filter:结果的筛选、过滤、格式化
⑤service:提供变量或者方法的服务
。。。
单页面应用的工作原理:
①url
http://127.0.0.1/index.html#/路由地址
②浏览器请求index.html,解析路由地址
③查找路由词典,#/start ==>tpl/start.html
④获取当前路由地址 对应的真是模板的地址 start.html
⑤发起ajax请求,获取目标模板页面,将服务器返回的代码片段,插入到当前的DOM树,实现局部刷新
使用ngRoute模块来实现SPA应用的基本步骤:
①创建完整的HTML页面 index.html,引入angular.js,angular-route.js
②创建自定义的模块,指定依赖于ng\ngRoute
③指定容器,盛放代码片段 ngView
④创建模板页面
⑤配置路由词典
⑥测试在地址栏中 输入不同的路由地址的时候,能否将代码片段加载进来。
模板页面之间 执行跳转的3种方式:
①直接修改地址栏中的url
②使用超链接 <a href=‘#/路由地址‘></a>
③$location.path(‘/路由地址‘)
如果有多个代码片段,都需要通过js的方式来跳转,为每个代码片段去创建控制器 去定义jump方法,这个是不合理的,可以这么处理:借助父控制器定义方法,然后让子控制器去调用。
配置代码片段的控制器的方式:
①ng-controller
②配置路由词典设置
$routeProvider.when(‘/myLogin‘,{
templateUrl:‘tpl/login.html‘,
controller:‘loginCtrl‘
});