🐰angular的学习资料 These are about angular learning materials, hoping to help you ⛄关于angular的常用知识点,DEMO和总结,不定时更新,欢迎fork和star On the common knowledge of angular, DEMO and summary, not regular updates, you can fork and star
Controller | |
---|---|
Angular控制器 | Angular表达式 |
Angular事件广播 | Angular基于$window的数据通信 |
bi-directional data binding |
---|
Angular的$watch,$apply和$digest |
Service | |
---|---|
Angular自定义服务的常用方法 | Angular部分服务demo |
Angular自定义Canvas画图服务 | Angular自定义http服务 面向对象封装 |
Angular的provider方法配置服务 |
Component | |
---|---|
Angular的component方法 |
Router | |
---|---|
Angular路由嵌套 | Angular路由单页多个ui-view |
Filter | |
---|---|
Angular内置过滤器 | Angular自定义关键词检索过滤器(1) |
Angular自定义关键词检索过滤器(2) | limitTo实现分页 |
Angular自定义关键词检索过滤器(简版) |
Animate | |
---|---|
Angular ng-animate动画1 | Angular ng-animate动画2 |
API |
---|
Angular常用api接口 |
FORM |
---|
Angular表单验证 |
Article | |
---|---|
ng-repeat绑定事件和嵌套 | Angular的post请求后台接受不了数据的解决方法 |
ionic总结 | ui-route和ng-route |
ng-options&&ng-switch | directive组件作用域 |
表单认证 | $broadcast,$emit and $on |
自定义过滤器 | 自定义手势指令ng-touch |
ng-animate | 单页面应用的技术点 |
HTML基础 | |
---|---|
video和audio标签Demo | canvas烟花效果 |
canvas烟花效果汇总 |
angular版本1.0是在 2012年发布的。 angular是由 Google的员工从2009年开始着手开发。 是一个非常好的构想,该项目由Google支持,有一个全职的开发团队继续开发和维护这个库。
当然我们要体验这个框架,就得先进行安装,打开nodejs的命令行,然后输入以下代码下载angula框架
npm install angular
注意:如果在这个后面加上@的话,就是制定版本下载
npm install angular@X.X.X
jQuery(jQ)工具库,angular(ng)是框架,框架比库大一个等级,
- 库是一堆封装的方法,
- 框架是一个图纸,不仅提供方法,还提供实现的思路
jQ比较轻量级,ng比较重(大而全面)
- 除了刚才npm下载
- 我们还可以在官网下载或者code.angularjs.org
- 或者使用CDN
jQ和ng
- 不要首先设计好你的页面,然后再通过DOM操作去修改它,先考虑数据驱动再考虑节点驱动
- 不要使用angularjs去扩展jQuery,首先要以angularjs的思维进行思考,我们再考虑jQuery,不要让jQuery成为你的拐杖,否则永远掌握不了angularjs,注意这里不代表说用angular就不能用jQ,只是新手建议先思考用angular解决问题,而不是优先考虑jQ
- 要以架构为中心进行思考,尝试模块化,组件化,封装服务,过滤器等方法解决问题,提高维护性,扩展性和复用性
有一点特别需要注意:如果页面中使用了jQuery和angular,那么一定要先加载jQuery框架,然后再加载angular
angular是一个 js框架。它是一个以js编写的库 在引入的时候一般使用未压缩版本 压缩和未压缩的区别在于,压缩的JS,是把一些变量名用简单的字符代替,然后把一些换行跟空格跟注释删掉
把Nodejs下载好的angular框架(未压缩版本)复制到项目JS目录,然后通过script
标签引入angular框架到HTML页面中
<script src="js/angular.js"></script>
angular是用模块化开发的,所以一般来说,一个angular程序就由一个主模块完成所有功能,一个主模块是由N个小模块组装成的
定义一个模块的方法就是angular.module()
方法,接受两个参数
angular.module("模块的名字",['引入分模块的名字'])
模块化开发,方便我们团队开发,方便分工合作,方便找出问题的根源
//定义一个模块,是一个模块函数,主模块
angular.module("app1",['app2','app3'])
//小模块
angular.module("app2",[])
angular.module("app3",[])
ng-app作为一个属性值可以放在任何标签上,建议放在<html>
和<body>
标签上,放在那个标签上,那就是主模块控制那个标签的闭合作用域
ng-app就是整个程序的作用域
ng-app="主模块的名字"
定义控制器就是用.controller()
在主模块的基础上链式调用,此函数第一个参数就是控制器的名字,第二个参数就是数组,数组里面放一个匿名函数,此匿名函数就是该控制器的逻辑
控制器是js对象,由标准的js对象的构造函数创建
ng-controller作为控制器的定义标签,放在ng-app闭合标签的范围内
angular.module("demo",[])
.controller("控制器的名字",[function(){
//code 控制器的逻辑
}])
.controller("控制器的名字",[function(){
}]);
oaoafly控制器和winds都是由demo主模块划分出来的小作用域(小地盘)
<html ng-app="demo">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div ng-controller="oaoafly">
</div>
<div ng-controller="winds">
</div>
</body>
<script>
angular.module("demo",[])
.controller("oaoafly",[function(){
//code 控制器的逻辑
}])
.controller("winds",[function(){
}]);
</script>
</html>
在大型的应用程序中,通常是把控制器存储在外部文件中
只需要把 <script>
标签中的代码复制到名为xxxController.js
的外部文件中即可
<html ng-app="demo">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div ng-controller="oaoafly">
</div>
<div ng-controller="winds">
</div>
</body>
<script src="controller/oaoaflyController.js"></script>
<script src="controller/windsController.js"></script>
</html>
写控制器的几种方法
//定义被angular控制器实例化的构造函数
function oaoaflyCtrl($scope){
//code 控制器的逻辑
}
angular.module("demo",[])
//(1)不建议这样写
.controller("oaoafly",oaoaflyCtrl)
//(2)不建议这样写 压缩代码的时候,注入的服务(形参)将被替换
.controller("winds",function($scope){
});
//(3)建议这样写 用中括号把函数和服务收集在一起,函数一定要写在最后面
//数组中的服务是字符串形式保留,一定要跟函数中的形参顺序一一对应
.controller("winds",["$scope",function($scope){
}]);
MVC是一种使用 MVC(Model View Controller 模型-视图-控制器)设计模式,该模型的理念被许多框架所吸纳,比如,后端框架(Struts、Spring MVC等)、前端框架(Angular、Backbone等)
如图所示:
M:model 模型也就是存取着数据(数据来自于后台ajax&jsonp$表单提交);
C:controller 控制器就是一个媒介,也就是连接着数据跟视图的一直无形手,是控制model与view之间的交互;
V:view 视图指的是HTML代码,也可以理解为页面呈现的状态。
M($scope绑定的值)--C-->V(ng-bind or {{}})
V(ng-model)--C-->M($scope绑定的值)
jQ是基于节点驱动的:$().val,$().text
ng是基于数据驱动的:ng-model,{{}}/ng-bind
定义完一个控制器后,在控制器的第二个参数(函数)里面注入一个$scope
的形参,$scope就是控制所在范围的绑定的值
控制器的$scope(相当于作用域、控制范围)用来保存angular中model(模型)的对象
angular的controller控制器中,要想将model模型中的数据传递给view视图,angular规定依附在$scope上的数据才能传递给视图
$scope
=>{{}}
$scope.name
=>{{name}}
模型层 M
$scope//是一个对象
$scope.name = "laoxie";
$scope.age = 18
视图层 V
<div ng-controller="abc">
<p>{{name}}</p>
<p>{{age}}</p>
</div>
控制层 C
.controller("abc",function($scope){
$scope//是一个对象
$scope.name = "Wscats Oaoafly";
$scope.age = 18
})
表达式:{{}},两个大括号可以放在任何地方(标签内,标签属性值内均可以),只要$scope定义了,{{}}对应显示对应的值,也就是在表达式书写的位置输出数据
如果表达式把数据绑定到 HTML,此时与 ng-bind
指令有异曲同工之妙
可以放在标签里面,可以放在属性值里面
<p>{{name}}</p>
<p id="{{name}}">{{name}}</p>
<style>
.blue{
color: {{color}};
}
</style>
angular表达式可以显示$scope定义的数据类型
//model
$scope.str = "Hello Oaoafly";
//view
<p>{{str}}<p>
//model
$scope.num = 520;
//view
<p>{{num}}<p>
//model
$scope.arr = ["Hello,"Oaoafly"];
//view
<p>{{arr[1]}}<p>
//model
$scope.bool = true;
//view
<p>{{bool?"Oaoafly":"Wscats"}}<p>
//model
$scope.obj = {
name:"Wscats"
};
//view
<p>{{obj.name}}<p>
angular表达式很像js表达式:它们可以包含文字、运算符和变量
<p>{{5+2*0}}</p>
<p>{{"Oaoafly"+name}}</p>
<!--三元表达式-->
<p>{{bool?"真":"假"}}</p>
如果把script
放在body
前面,那么就会先加载JS,因为一般JS比较大,所以阻塞这个HTML结构的渲染
反之,为了用户体验,就先加载HTML结构,再加载JS
一般我们也会把link
放在body
前面,因为CSS一般比较小,并且我们要渲染页面就先需要样式,不然排版就会混乱
angular框架自带的一套属性值,往这个属性值放制定值就呈现不同逻辑, angular写了一套新属性称为指令的东西来扩展HTML,可以理解为简化我们操作DOM方法的封装
ng-XX="" //内置指令都带有前缀ng-
ng-app //告诉ng框架,<div>元素是ng应用程序 的"所有者"和"控制者"
ng-controller //定义了应用程序控制器
ng-init //初始化应用程序数据
ng-click = "function"
ng-bind = "name" ==> {{name}}
ng-model = "" //此指令一般配合input select textarea标签使用
ng-repeat = "array" "单项(名字随意) in 数组" 一般配合ul select table标签使用
ng-show = "bool""接受一个布尔值" 如果为真则显示,反之则隐藏
ng-if = "bool" ng-if直接把DOM节点删除,或者插入DOM节点,ng-if比ng-show效率高一点
ng-class = "object" ng-class接受的对象,对象名就是这个类名,属性值就是布尔值,如果右边的布尔值为真,那左边的类就出现,反之就隐藏
ng-src="{{路径}}"
ng-href="{{路径}}"
ng-switch="变量"配合ng-switch-when=""
引入JS的地方会影响表达式{{}}
的效果,所以注意:
- 你如果用
ng-bind
,那就可以把JS放在body
下面(严谨用这种) - 如果用
{{}}
,那最好把JS放在body
上面(喜欢偷懒用这种)
Angular实现了双向绑定机制。所谓的双向绑定,无非是从界面的操作能实时反映到数据,数据的变更能实时展现到界面。即数据模型(Model)和视图(View)之间的双向绑定
双向绑定的原理从脏检查机制开始说起 脏检查机制:Angular将双向绑定转换为一堆watch表达式,然后递归这些表达式检查是否发生过变化,如果变了则执行相应的watcher函数(指view上的指令,如ng-bind,ng-show等或是{{}})。等到model中的值不再发生变化,也就不会再有watcher被触发,一个完整的digest循环就完成了。
脏检查机制的触发:Angular中在view上声明的事件指令,如:ng-click、ng-change等,会将浏览器的事件转发给$scope上相应的model的响应函数。等待相应函数改变model,紧接着触发脏检查机制刷新view。
所以,上文中的代码无法实现相应功能的原因就是缺乏触发Angular脏检查机制的条件,而手动添加了scope.$digest()使其执行了脏检查机制更新了view。 watch表达式:可以是一个函数、可以是$scope上的一个属性名,也可以是一个字符串形式的表达式。$watch函数所监听的对象叫做watch表达式。 watcher函数:指在view上的指令(ngBind,ngShow、ngHide等)以及{{}}表达式,他们所注册的函数。每一个watcher对象都包括:监听函数,上次变化的值,获取监听表达式的方法以及监听表达式,最后还包括是否需要使用深度对比(angular.equals())。
脏检查机制(dirty-checking)是实现双向数据绑定的重要基础
Angular中的$digest函数:当接受view上的事件指令转发的事件时,就会切换到Angular的上下文环境,来影响这类事件,$digest循环就会触发
Angular中的$digest函数:当接受view上的事件指令转发的事件时,就会切换到Angular的上下文环境,来影响这类事件,$digest循环就会触发。
遍历一遍所有的watcher函数就是一轮脏检查,执行完一轮之后,只要有watcher监听的值改变过,那么就会重新在进行一轮,直到所有的值都没有变化。从第一轮到所有数据稳定称为一个完整的$digest循环。当循环结束后,才把模型的变化结果更新到dom中去,防止频繁的dom操作。
我们已经知道什么时候以及怎么开始digest循环了,那么digest循环具体做了些什么?
在digest循环中,AngularJS会遍历整个$watch列表,所有watcher都会被触发,当一个wathcer被触发时,AngularJS会检测Scope模型相应的数据,如果它发生了变化,那么关联到该watcher的回调函数就会被触发。
如果执行了一次digest循环后某个值发生了变化,那么AngularJS会再次循环,直至不再有任何变化。这是因为你在$watch中更新某个值,如果该值对应的$watch已在这遍循环通过,AngularJS将检测不到变化无法更新。如果循环运行了10次或更多次,AngularJS会抛出异常并停止。(就算没有更新值,AngularJS也会多运行一次来确保没有改变,也就是至少运行两次)。
参考Angular的$watch,$apply和$digest
服务是一个函数或单例对象,就相当于我们可以在angular程序中封装好一些方法然后在需要用的时候注入到需要用到的地方(控制器,自定义过滤器,自定义指令和自定义服务中),这样可以增强我们程序的扩展性和复用性
即无论这个服务被注入到任何地方,对象始终只有一个实例
服务被定义在一个模块中,所以其使用范围是可以被我们管理的。ng的避免全局变量污染意识非常强
在angular中有相当多内置服务,下面列出常用的一些内置服务
$scope
是控制器独有的服务,$scope是控制器的作用域,也就是用来绑定数据模型的一个服务
是ng-app的作用域范围,它可以用在两个控制器之间传递数据,你可以把它看做ng的全局作用域
数据流动方向
font-end v->c(ng-model/ng-bind/{{}})->m--$http-->back-end
back-end--$http-->m->c((ng-model/ng-bind/{{}}))-> v
$http 是angular中最常用的服务,用于服务器的数据传输,是对ajax,jsonp等方法的封装
旧版:
$http.post("Wscats.php", {
params: {}
})
.success(function(data){
//成功的回调
})
.error(function(err){
//失败的回调
})
新版:
$http({
method:"get",
url:"Oaoafly.php"
params:{}
})
.then(function(data){
//成功的回调
},function(err){
//失败的回调
})
Jsonp 跨域,它本质就是动态创建
script
标签,然后利用src这个属性值的跨域能力,实现数据请求
注意POST请求跟jQ是不一样的,jQ是返回字符串,ng返回对象,引入一个ngPost来去改写
处理html为安全字符的一个服务
ng-bind-html输出html格式,配合$sce服务
//view
<div ng-bind-html="html"></div>
//model
$scope.html = "<p>Hello Wscat</p>";
$scope.html = $sce.trustAsHtml($scope.html)
这个服务可以注入到过滤器或者控制器里面
$filter("过滤器名字")("处理的数据","过滤器的参数")
$location提供地址栏相关的服务
url = http://qiaole.sinaapp.com?#name=cccccc
$location.absUrl();
// http://qiaole.sinaapp.com?#name=cccccc
$location.host();
// qiaole.sinaapp.com
$location.port();
// 80
$location.protocol();
// http
$location.url();
// ?#name=cccccc
// 获取url参数
$location.search().name;
// or
$location.search()['name'];
$location 服务,它可以使用 DOM 中存在的对象,类似 window.location 对象,但 window.location 对象在angular应用中有一定的局限性。 angular会一直监控应用,处理事件变化, angular使用 $location服务比使用 window.location对象更好。
- $timeout服务对应了JS的window.setTimeout函数
- $interval服务对应了JS的window.setInterval函数
$scope.interval = 0;
$scope.timeout = 0;
$timeout(function(){
$scope.timeout = 1;
},1000)
$interval(function(){
$scope.interval++
},1000)
- $window服务对应了JS的全局window
- $document服务对应了JS的document,用的时候注意要这样用$document[0]
$provide服务负责告诉Angular如何创造一个新的可注入的东西:即服务。服务会被叫做供应商的东西来定义,你可以使用$provide来创建一个供应商。你需要使用$provide中的provider()方法来定义一个供应商,同时你也可以通过要求$provide被注入到一个应用的config函数中来获得$provide服务。
定义常量用的,它定义的值当然就不能被改变,它可以被注入到任何地方,但是不能被装饰器(decorator)装饰
//constant定义常量
app.constant('c','Wscats is cat')
它可以是string,number甚至function,它和constant的不同之处在于,它可以被修改,不能被注入到config中,但是它可以被decorator装饰
app.value('c','Wscats is cat')
它是一个可注入的function,它和service的区别就是:factory是普通function,而service是一个构造器(constructor),这样angular在调用service时会用new关键字,而调用factory时只是调用普通的function,所以factory可以返回任何东西,而service可以不返回
factory可以返回任何东西,它实际上是一个只有$get方法的provider
app.factory('Math', function() {
var obj = {
add: function(a, b) {
return a + b;
},
multipy: function(a, b) {
return a * b
},
num:1,
str:"oaoafly.js"
}
return obj;
})
service其实一个构造器,但我们注入这个服务的时候,就会自动帮我们new,创建这个对象
它是一个可注入的构造器,在angular中它是单例的,用它在控制器中通信或者共享数据都很合适
在service里面可以不用返回东西,因为angular会调用new关键字来创建对象。返回一个自定义对象也不会出错,此时类似factory方法
app.service('Math', function() {
this.add = function(a, b) {
return a + b;
};
this.multipy = function(a, b) {
return a * b
};
this.num=1;
this.str="wscats.php";
})
provider是他们的老大,上面的几乎(除了constant)都是provider的封装,provider必须有一个$get方法,当然也可以说provider是一个可配置的factory
Decorator 这个比较特殊,它不是provider,它是用来装饰其他provider的,而前面也说过,他不能装饰Constant,因为实际上Constant不是通过provider()方法创建的
var app = angular.module('app', []);
app.value('movieTitle', 'The Matrix');
app.config(function ($provide) {
$provide.decorator('movieTitle', function ($delegate) {
return $delegate + ' - starring Keanu Reeves';
});
});
app.controller('myController', function (movieTitle) {
expect(movieTitle).toEqual('The Matrix - starring Keanu Reeves');
});
所有的供应商都只被实例化一次,也就说他们都是单例的 除了constant,所有的供应商都可以被装饰器(decorator)装饰
- value就是一个简单的可注入的值
- service是一个可注入的构造器
- factory是一个可注入的方法
- decorator可以修改或封装其他的供应商,当然除了constant
- provider是一个可配置的factory
参考AngularJS中的Provider们:Service和Factory等的区别
- Angular基于$window的数据通信
- Angular事件广播
- $rootScope
- 路由传参(跨页面跨路由的情况)
- Cookies和本地存储
- 基于服务器通信数据
$broadcast:向下(子)广播事件
$scope.$broadcast('事件名字', '传递的值');
$emit:向上(父)广播事件
$scope.$emit('事件名字', '传递的值');
$on:接受广播事件
$scope.$on('事件名字', function(event, data) {
//data 就是传递过来的值
})
发送事件
向父控制器传递信息
$scope.$emit('name', 'args');
向子控制器传递信息
$scope.$broadcast('name', 'args');
- name:事件的名字
- args:事件所需要传递的参数
接受事件
接受来自于子或父传来的信息(仅此一个方法可以接受事件)
$scope.$on('name',function(event,data){
//从$emit或者$broadcast中获取的args事件传递来的信息
})
类型 | 方法 |
---|---|
无直接关联的控制器 | 使用 $rootScope.$emit() 、 $rootScope.$boardcast() 或 $scope.$emit 来发出数据,通过 $rootScope.$on() 来获取数据 |
父控制器到子控制器 | 父控制器使用 $scope.$boradcast() 来发送数据,子控制器通过 $scope.$on() 来获取数据 |
子控制器至父控制器 | 子控制器使用 $scope.$emit() 来发送数据,父控制器通过 $scope.$on() 来获取数据 |
单例服务是 angular本身支持的数据和代码共享方式,因为是单例的,所有的控制器访问的便是同一份数据
app.service("exchangeService", function() {
return {
//两个控制器共享的数据
content: "Hello Oaoafly"
}
})
定义一个空服务或者定义一个返回对象的服务,将exchangeService
注入到不同的控制器中,控制器就可以都得到服务中的content
,因为服务是单例的,所以
其中一个服务修改content
数据,其他服务都会得到其新值,从而完成控制器之间的数据通信
也可以通过$window中定义一个storage的对象
app.run(function($window) {
//类似redux vuex
$window.storage = {
state: {
//初始化的值
name: "Oaoafly Wscats"
}
}
然后注入到对应的服务中完成通信,通过$scope.$watch
监听值的改变从而完成对应的逻辑
app.controller("indexCtrl", function($scope, $window) {
$scope.name = "Oaoafly";
$scope.$watch("name", function() {
$window.storage.name = $scope.name;
})
})
app.controller("homeCtrl", function($scope, $window) {
// 监听修改
$scope.$watch(function() {
return $window.storage.name;
}, function(n) {
$scope.name = n;
});
})
app.direcitve("指令的名字",自定义指令的函数(逻辑))
属性值形式则为指令,标签形式就是组件
使用驼峰命名法的时候注意,比如自定义ngTouch
指令,使用则是ng-touch
,使用-
来代替驼峰命名法,AngularJS本身已经使用了ng-
前缀,所以可以选择除此以外的名字,尽量少用ng作为指令的前缀
ECMA:
值 | value |
---|---|
element | 元素,标签 |
attribute | 属性 |
class | 类 |
m | 注释 |
如果不写就是默认所有形式都可以呈现,可以支持"EA"和"EAMC"
- 尽量少用ng-XXX前缀自定义指令
- 尽量少用HTML定义好的标签,比如header,footer,nav
如果组件html结构比较简单我们用template
,如果组件html结构比较复杂我们用templateUrl
templateUrl获取html所在的文件路径
接受一个布尔值 如果replace是真的话,那组件的标签会被html结构替换,如果replace是false的话,那么组件的标签名会出现,那方便我们分组管理这些组件
绑定指令内部使用的数据
controller : ['$scope',function($scope){
//共享数据存放在这里
$scope.name = "Wscats";
//使用this共享给其他指令 传递数据被transclude插槽中的子组件
this.name = "Wscats";
}],
link接受一个匿名函数,该匿名函数有三个形参(scope,ele,attr)
link:function(scope,ele,attr){
//link 无非就是组件的控制器 存放该组件数据模型
//model
scope.name = "lan";
scope.text = "第一个组件,";
scope.Click = function(){
console.log("click")
}
}
scope
link函数就是控制该组件的逻辑,可以给组件提供数据模型(对scope绑定字符串,布尔值,数字,函数...) 可以理解为组件内部的控制器
ele
如果我们的项目里面用引用jQuery,我们可以把节点交给jq处理,$(ele),如果我们没有引入jQuery,那么我们就用jQLite jQlite是jQuery的小型版本,两者是不冲突,下面就是jQlite的接口文档
方法 | 用处 |
---|---|
addClass() | 为每个匹配的元素添加指定的样式类名 |
after() | 在匹配元素集合中的每个元素后面插入参数所指定的内容,作为其兄弟节点 |
append() | 在每个匹配元素里面的末尾处插入参数内容 |
attr() | 获取匹配的元素集合中的第一个元素的属性的值 |
bind() | 为一个元素绑定一个事件处理程序 |
children() | 获得匹配元素集合中每个元素的子元素,选择器选择性筛选 |
clone() | 创建一个匹配的元素集合的深度拷贝副本 |
contents() | 获得匹配元素集合中每个元素的子元素,包括文字和注释节点 |
css() | 获取匹配元素集合中的第一个元素的样式属性的值 |
data() | 在匹配元素上存储任意相关数据 |
detach() | 从DOM中去掉所有匹配的元素 |
empty() | 从DOM中移除集合中匹配元素的所有子节点 |
eq() | 减少匹配元素的集合为指定的索引的哪一个元素 |
find() | 通过一个选择器,jQuery对象,或元素过滤,得到当前匹配的元素集合中每个元素的后代 |
hasClass() | 确定任何一个匹配元素是否有被分配给定的(样式)类 |
html() | 获取集合中第一个匹配元素的HTML内容 |
next() | 取得匹配的元素集合中每一个元素紧邻的后面同辈元素的元素集合。如果提供一个选择器,那么只有紧跟着的兄弟元素满足选择器时,才会返回此元素 |
on() | 在选定的元素上绑定一个或多个事件处理函数 |
off() | 移除一个事件处理函数 |
one() | 为元素的事件添加处理函数。处理函数在每个元素上每种事件类型最多执行一次 |
parent() | 取得匹配元素集合中,每个元素的父元素,可以提供一个可选的选择器 |
prepend() | 将参数内容插入到每个匹配元素的前面(元素内部) |
prop() | 获取匹配的元素集中第一个元素的属性(property)值 |
ready() | 当DOM准备就绪时,指定一个函数来执行 |
remove() | 将匹配元素集合从DOM中删除。(同时移除元素上的事件及 jQuery 数据。) |
removeAttr() | 为匹配的元素集合中的每个元素中移除一个属性(attribute) |
removeClass() | 移除集合中每个匹配元素上一个,多个或全部样式 |
removeData() | 在元素上移除绑定的数据 |
replaceWith() | 用提供的内容替换集合中所有匹配的元素并且返回被删除元素的集合 |
text() | 得到匹配元素集合中每个元素的合并文本,包括他们的后代 |
toggleClass() | 在匹配的元素集合中的每个元素上添加或删除一个或多个样式类,取决于这个样式类是否存在或值切换属性。即:如果存在(不存在)就删除(添加)一个类 |
triggerHandler() | 为一个事件执行附加到元素的所有处理程序 |
unbind() | 从元素上删除一个以前附加事件处理程序 |
val() | 获取匹配的元素集合中第一个元素的当前值 |
wrap() | 在每个匹配的元素外层包上一个html元素 |
共用的数据模型最好放到link函数里面定义,不共用的最好放到控制器里面
attr
获取该组件父节点的属性值,注意replace的取值,如果要拿组件replace的属性值最好把replace设置为replace:false
因为要获取自定义组件标签上的属性值,这样才有意义
- true:除了第一次绑定的时候,父能影响子,子不能影响父
- false:父子之间相互影响
- {}:父子互不影响,就是独立作用域 false和{}是比较常用,默认scope就是false
=
双向数据绑定,注意此时name属性值的变量要带{{}}
<wsscat2 name="{{name}}"></wsscat2>
scope: {
name:"="
},
@
当方向影响,父能影响子,但子不能影响父
<wsscat2 name="name"></wsscat2>
scope: {
name:"@"
},
一定要把绑定的值放在属性上面作为媒介
属性值不能设置为如data-name
的data-
前缀的值
如果是设置为abc-name
等格式
组件里面scope
属性传递的对象,里面的name属性值要遵守驼峰的写法
scope: {
name:"@abcName"
},
我们可以使用指令directive
或者组件component
方法来封装swiper的组件
下载Swiper完整安装包
- 把插件的html和css部分放在,templateUrl模板里面(视图)
- 把插件的js部分放在link函数里面(逻辑)
过滤器可以通过一个管道字符(|)和一个过滤器添加到表达式中
{{num|过滤器的名字:参数}}
可以在后面接上其他参数来更改货币符号
Model
$scope.num = 100000;
View
<p>{{num|currency : '¥'}}</p>
Model
$scope.date = 1477966081000;//时间戳(精确到毫秒)
View
<p>{{date|date:'yyyy/MM/dd hh:mm:ss EEEE'}}</p>
orderBy
接受一个布尔值,实现排序filter
可以接受字符串,即需要筛选的键值名,也可以接受一个对象,实现筛选limitTo
接受两个数字,第一个数字是长度,第二个是索引值,可以用在数组也可以用在字符串截取上
//Model
$scope.filter = "name";
$scope.orderBy = true;
$scope.names = [{
name: 'Wscats',
id: 1
}, {
name: 'Oaoafly',
id: 3
}, {
name: 'Windiest',
id: 2
}];
//View
<ul>
<li ng-repeat="name in names|filter:filter|orderBy:'id':orderBy|limitTo:2">{{name.name}}</li>
</ul>
//Model
$scope.name = 'wSsCat';
//View
<p>{{name|uppercase}}</p>
<p>{{name|lowercase}}</p>
json过滤器可以把一个js对象格式化为json字符串,没有参数,作用就和我们熟悉的JSON.stringify()
一样,一般用于调试
<p>{{obj|json}}</p>
number过滤器可以为一个数字加上千位分割,像这样,123,456,789,同时接收一个参数,可以指定小float类型保留几位小数
Model
$scope.num = 100000;
View
<p>{{num|number:2}}</p>
filter | methods |
---|---|
currency | currency:"货币符号" |
uppercase | uppercase大写 |
lowercase | lowercase小写 |
filter | 接受一个对象,一般配合ng-repeat |
orderBy | 接受两个参数,第一个是要排序的键值,第二个是个布尔值 |
limitTo | 可以用于分页,第一个参数就是截取的长度,第二个是截取的位置,可以用于截取字符串和数组 |
json | 就是把对象转为字符串显示,一般用于调试页面数据 |
date | 接受时间戳格式,处理成常用的时间格式 |
number | 精确到就是小数点后几位 |
app.filter("过滤器名字",function("服务")){
return function("传入需要处理的值"){
return "返回处理完的值"
}
}
UI路由
开始引入angular和ui-route的js文件
<script type="text/javascript" src="angular.js" ></script>
<script type="text/javascript" src="angular-ui-router.js"></script>
与原生angular路由不同的是,ui路由用ui-view而不是ng-view
<div ui-view></div>
在angular服务中注入ui.router模块
var app = angular.module('wscats', ['ui.router']);
用到**$stateProvider和$urlRouterProvider**两个服务
/* 注入$stateProvider,$urlRouterProvider */
app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
/* 使用when来对一些不合法的路由进行重定向 */
$urlRouterProvider.when('', '/main');
/* 通过$stateProvider的state()函数来进行路由定义 */
$stateProvider.state('main', {
url: '/main',
templateUrl: 'views/main.html',
controller: 'mainCtrl'
}).state('main.a', {
url: '/pageMain1',
templateUrl: 'views/pageMain1.html',
controller: 'pageMain1Ctrl'
})
}]);
主路由,路由地址为#/main
app.controller('mainCtrl', function($scope) {
$scope.name = 'Wscats';
})
main路由下的子路由,路由地址为#/main/pageMain1
app.controller('pageMain1Ctrl',function($scope){
$scope.name = 'Oaoafly'
})
此时我们就可以在main.html上放第二个ui-view
这里比原生好的地方在于可以嵌套路由
main.html
<!--main-->
{{name}}
<div ui-view></div>
pageMain1.html
<!--pageMain1-->
{{name}}
我们在生成一个新的子控制器
.state('main.b', {
url: '/pageMain2/:id',
templateUrl: 'views/pageMain2.html',
controller: 'pageMain2Ctrl'
})
留意我们在url定义的路由中多了个:id
,这样我们就可以在控制器之间传递参数
url: '/pageMain2/:id'
在控制器中我们注入$state服务
app.controller('pageMain2Ctrl', function($scope, $state) {
$scope.name = 'Hello Wscats Oaoafly'
console.log($state.params);
})
用$state.params
就可以访问到路由上的参数
例如我们输入#/main/pageMain2/1,就会返回一个对象Object {id: "1"}
当一个视图拥有多个ui-view,例如下面这样,平时我们一般一个视图只有一个ui-view
的情况
<div ui-view name="first"></div>
<div ui-view name="second"></div>
当拥有多个这样的ui-view
我们就要加上name属性,并绑定它到路由配置中的views属性,让子视图决定渲染到哪一个ui-view
里面
.state('main.a', {
url: '/pageMain1',
views: {
"first": {
templateUrl: 'views/pageMain1.html',
controller: 'pageMain1Ctrl'
}
}
}).state('main.b', {
url: '/pageMain2/:id',
views: {
"first": {
templateUrl: 'views/pageMain2.html',
controller: 'pageMain2Ctrl'
}
}
}).state('main.c', {
url: '/pageMain3/:id',
views: {
"second": {
templateUrl: 'views/pageMain3.html',
controller: 'pageMain3Ctrl'
}
}
})