Giter Site home page Giter Site logo

angular-tutorial's Introduction

Angular-tutorial code by Wsscat

🐰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的数据通信
Angular表达式执行函数

双向数据绑定

bi-directional data binding
Angular的$watch,$apply和$digest

服务

Service
Angular自定义服务的常用方法 Angular部分服务demo
Angular自定义Canvas画图服务 Angular自定义http服务 面向对象封装
Angular的provider方法配置服务 Angular基于服务的数据通信

组件与指令

Directive
Angular自定义手势指令 Angular自定义轮播图组件
Angular自定义下拉刷新组件1 Angular自定义下拉刷新组件2
Angular内置指令 Angular自定义点击返回顶部指令
Angular实现选项卡(1) Angular实现选项卡(2)
Angular封装swiper轮播图 Angular中使用ng-switch
Angular的ng-transclude Angular侧边栏组件
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

API
Angular常用api接口

表单验证

FORM
Angular表单验证

项目

Guess you like
Angular商城Demo Angular的Cnode社区
AngularStovepipe Angular的新闻客户端
Angular商城Demo Angular的Cnode社区
Angular内联编辑器 Angular即时搜索
Angular导航菜单 Angular订单表单
Angular切换网格 Angular新闻+WEUI DEMO 源码
Angular+Weui单页面应用DEMO-每日笑话

文档

Article
ng-repeat绑定事件和嵌套 Angular的post请求后台接受不了数据的解决方法
ionic总结 ui-route和ng-route
ng-options&&ng-switch directive组件作用域
表单认证 $broadcast,$emit and $on
自定义过滤器 自定义手势指令ng-touch
ng-animate 单页面应用的技术点

其他

Other
Angular三级联动(1) Angular三级联动(2)
Angular事件监听 Angular事件广播
Angular利用angular.module()实现模块化 Angular的form表单验证
Angular的ng-repeat嵌套 NodeJs静态服务器
Angular利用angular.module()实现模块化2 Angular+Webpack
Angular中使用iframe 百度定位DEMO
Angular自定义cookie服务和ngCookie的使用 Angular调用百度API接口实现公交路线查询
Angular调用百度API接口实现公交号查询

JS基础

JS基础
Javascript的createElement Javascript的createDocumentFragment
Javascript的节点关系型API Javascript的节点创建型API
Javascript的节点查询型API Javascript的页面修改型API
像素帧动画 jQuery模拟ng-repeat
lessDemo lessDemo的less文件
图灵机器人 sessionStorage和localStorage

HTML基础

HTML基础
video和audio标签Demo canvas烟花效果
canvas烟花效果汇总 canvas弹幕效果

CSS基础

CSS基础
css浮动 flex布局

Install

angular版本1.0是在 2012年发布的。 angular是由 Google的员工从2009年开始着手开发。 是一个非常好的构想,该项目由Google支持,有一个全职的开发团队继续开发和维护这个库。

当然我们要体验这个框架,就得先进行安装,打开nodejs的命令行,然后输入以下代码下载angula框架

npm install angular

注意:如果在这个后面加上@的话,就是制定版本下载

npm install angular@X.X.X

jQuery(jQ)工具库,angular(ng)是框架,框架比库大一个等级,

  1. 库是一堆封装的方法,
  2. 框架是一个图纸,不仅提供方法,还提供实现的思路

jQ比较轻量级,ng比较重(大而全面)

  1. 除了刚才npm下载
  2. 我们还可以在官网下载或者code.angularjs.org
  3. 或者使用CDN

jQ和ng

  1. 不要首先设计好你的页面,然后再通过DOM操作去修改它,先考虑数据驱动再考虑节点驱动
  2. 不要使用angularjs去扩展jQuery,首先要以angularjs的思维进行思考,我们再考虑jQuery,不要让jQuery成为你的拐杖,否则永远掌握不了angularjs,注意这里不代表说用angular就不能用jQ,只是新手建议先思考用angular解决问题,而不是优先考虑jQ
  3. 要以架构为中心进行思考,尝试模块化,组件化,封装服务,过滤器等方法解决问题,提高维护性,扩展性和复用性

有一点特别需要注意:如果页面中使用了jQuery和angular,那么一定要先加载jQuery框架,然后再加载angular

Require

angular是一个 js框架。它是一个以js编写的库 在引入的时候一般使用未压缩版本 压缩和未压缩的区别在于,压缩的JS,是把一些变量名用简单的字符代替,然后把一些换行跟空格跟注释删掉

把Nodejs下载好的angular框架(未压缩版本)复制到项目JS目录,然后通过script标签引入angular框架到HTML页面中

<script src="js/angular.js"></script>

Module

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

定义控制器就是用.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){
	}]);

Angular控制器DEMO

MVC MVVM

MVC是一种使用 MVC(Model View Controller 模型-视图-控制器)设计模式,该模型的理念被许多框架所吸纳,比如,后端框架(Struts、Spring MVC等)、前端框架(Angular、Backbone等) 如图所示: image 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就是控制所在范围的绑定的值

控制器的$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
})

Expression

表达式:{{}},两个大括号可以放在任何地方(标签内,标签属性值内均可以),只要$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>

引入JS的地方

如果把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的地方会影响表达式{{}}的效果,所以注意:

  1. 你如果用ng-bind,那就可以把JS放在body下面(严谨用这种)
  2. 如果用{{}},那最好把JS放在body上面(喜欢偷懒用这种)
指令 作用
ng-app 定义应用程序的根元素。
ng-bind 绑定 HTML 元素到应用程序数据
ng-bind-html 绑定 HTML 元素的 innerHTML 到应用程序数据,并移除 HTML 字符串中危险字符
ng-bind-template 规定要使用模板替换的文本内容
ng-blur 规定blur事件的行为
ng-change 规定在内容改变时要执行的表达式
ng-checked 规定元素是否被选中
ng-class 指定 HTML 元素使用的 CSS类
ng-class-even 类似 ng-class,但只在偶数行起作用
ng-class-odd 类似 ng-class,但只在奇数行起作用
ng-click 定义元素被点击时的行为
ng-cloak 在应用正要加载时防止其闪烁
ng-controller 定义应用的控制器对象
ng-copy 规定拷贝事件的行为
ng-csp 修改内容的安全策略
ng-cut 规定剪切事件的行为
ng-dblclick 规定双击事件的行为
ng-disabled 规定一个元素是否被禁用
ng-focus 规定聚焦事件的行为
ng-form 指定 HTML表单继承控制器表单
ng-hide 隐藏或显示 HTML元素
ng-href 为 the元素指定链接
ng-if 如果条件为 false移除 HTML元素
ng-include 在应用中包含 HTML文件
ng-init 定义应用的初始化值
ng-jq 定义应用必须使用到的库,如:jQuery
ng-keydown 规定按下按键事件的行为
ng-keypress 规定按下按键事件的行为
ng-keyup 规定松开按键事件的行为
ng-list 将文本转换为列表 (数组)
ng-model 绑定 HTML 控制器的值到应用数据
ng-mousedown 规定按下鼠标按键时的行为
ng-model-options 规定如何更新模型
ng-mouseenter 规定鼠标指针穿过元素时的行为
ng-mouseleave 规定鼠标指针离开元素时的行为
ng-mousemove 规定鼠标指针在指定的元素中移动时的行为
ng-mouseover 规定鼠标指针位于元素上方时的行为
ng-mouseup 规定当在元素上松开鼠标按钮时的行为
ng-non-bindable 规定元素或子元素不能绑定数据
ng-open 指定元素的open属性
ng-options <select>列表中指定 <options>
ng-paste 规定粘贴事件的行为
ng-pluralize 根据本地化规则显示信息
ng-readonly 指定元素的readonly属性
ng-repeat 定义集合中每项数据的模板
ng-selected 指定元素的selected属性
ng-show 显示或隐藏HTML元素
ng-src 指定 元素的src属性
ng-srcset 指定 元素的srcset属性
ng-style 指定元素的 style属性
ng-submit 规定 onsubmit事件发生时执行的表达式
ng-switch 规定显示或隐藏子元素的条件
ng-transclude 规定填充的目标位置
ng-value 规定 input元素的值

Angular内置指令DEMO 详情可参考文档

双向绑定

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是控制器独有的服务,$scope是控制器的作用域,也就是用来绑定数据模型的一个服务

$rootScope

是ng-app的作用域范围,它可以用在两个控制器之间传递数据,你可以把它看做ng的全局作用域

$http

数据流动方向

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来去改写

$sce

处理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)

$fiter服务

这个服务可以注入到过滤器或者控制器里面

$filter("过滤器名字")("处理的数据","过滤器的参数")

$location

$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和$interval

  1. $timeout服务对应了JS的window.setTimeout函数
  2. $interval服务对应了JS的window.setInterval函数
$scope.interval = 0;
$scope.timeout = 0;
$timeout(function(){
	$scope.timeout = 1;
},1000)
$interval(function(){
	$scope.interval++
},1000)

$window和$document

  1. $window服务对应了JS的全局window
  2. $document服务对应了JS的document,用的时候注意要这样用$document[0]

自定义服务

image

$provide(供应商)

$provide服务负责告诉Angular如何创造一个新的可注入的东西:即服务。服务会被叫做供应商的东西来定义,你可以使用$provide来创建一个供应商。你需要使用$provide中的provider()方法来定义一个供应商,同时你也可以通过要求$provide被注入到一个应用的config函数中来获得$provide服务。

Constant

定义常量用的,它定义的值当然就不能被改变,它可以被注入到任何地方,但是不能被装饰器(decorator)装饰

//constant定义常量
app.constant('c','Wscats is cat')

Value

它可以是string,number甚至function,它和constant的不同之处在于,它可以被修改,不能被注入到config中,但是它可以被decorator装饰

app.value('c','Wscats is cat')

Factory

它是一个可注入的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

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

provider是他们的老大,上面的几乎(除了constant)都是provider的封装,provider必须有一个$get方法,当然也可以说provider是一个可配置的factory

Angular的provider配置服务

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)装饰

  1. value就是一个简单的可注入的值
  2. service是一个可注入的构造器
  3. factory是一个可注入的方法
  4. decorator可以修改或封装其他的供应商,当然除了constant
  5. provider是一个可配置的factory

参考AngularJS中的Provider们:Service和Factory等的区别

控制器之间通信数据

  1. Angular基于$window的数据通信
  2. Angular事件广播
  3. $rootScope
  4. 路由传参(跨页面跨路由的情况)
  5. Cookies和本地存储
  6. 基于服务器通信数据

通过事件通信数据

$broadcast:向下(子)广播事件

$scope.$broadcast('事件名字', '传递的值');

$emit:向上(父)广播事件

$scope.$emit('事件名字', '传递的值');

$on:接受广播事件

$scope.$on('事件名字', function(event, data) {
	//data 就是传递过来的值
})

发送事件

向父控制器传递信息

$scope.$emit('name', 'args');

向子控制器传递信息

$scope.$broadcast('name', 'args');
  1. name:事件的名字
  2. 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作为指令的前缀

restrict

ECMA:

value
element 元素,标签
attribute 属性
class
m 注释

如果不写就是默认所有形式都可以呈现,可以支持"EA"和"EAMC"

  1. 尽量少用ng-XXX前缀自定义指令
  2. 尽量少用HTML定义好的标签,比如header,footer,nav

template和templateUrl

如果组件html结构比较简单我们用template,如果组件html结构比较复杂我们用templateUrl templateUrl获取html所在的文件路径

replace

接受一个布尔值 如果replace是真的话,那组件的标签会被html结构替换,如果replace是false的话,那么组件的标签名会出现,那方便我们分组管理这些组件

controller

绑定指令内部使用的数据

controller : ['$scope',function($scope){
	//共享数据存放在这里
	$scope.name = "Wscats";
	//使用this共享给其他指令 传递数据被transclude插槽中的子组件
	this.name = "Wscats";
}],

transclude

Angular的ng-transclude

link

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 因为要获取自定义组件标签上的属性值,这样才有意义

scope

  1. true:除了第一次绑定的时候,父能影响子,子不能影响父
  2. false:父子之间相互影响
  3. {}:父子互不影响,就是独立作用域 false和{}是比较常用,默认scope就是false

=

双向数据绑定,注意此时name属性值的变量要带{{}}

<wsscat2 name="{{name}}"></wsscat2>
scope: {
     name:"="
},

@

当方向影响,父能影响子,但子不能影响父 <wsscat2 name="name"></wsscat2>

scope: {
     name:"@"
},

一定要把绑定的值放在属性上面作为媒介 属性值不能设置为如data-namedata-前缀的值 如果是设置为abc-name等格式 组件里面scope属性传递的对象,里面的name属性值要遵守驼峰的写法

scope: {
     name:"@abcName"
},

封装swiper的组件

我们可以使用指令directive或者组件component方法来封装swiper的组件 下载Swiper完整安装包

  1. 把插件的html和css部分放在,templateUrl模板里面(视图)
  2. 把插件的js部分放在link函数里面(逻辑)

Angular封装swiper轮播图组件

语法

过滤器可以通过一个管道字符(|)和一个过滤器添加到表达式中

{{num|过滤器的名字:参数}}

currency

可以在后面接上其他参数来更改货币符号

Model
$scope.num = 100000;
View
<p>{{num|currency : '¥'}}</p>

date

Model
$scope.date = 1477966081000;//时间戳(精确到毫秒)
View
<p>{{date|date:'yyyy/MM/dd hh:mm:ss EEEE'}}</p>

orderBy和filter和limitTo

  1. orderBy接受一个布尔值,实现排序
  2. filter可以接受字符串,即需要筛选的键值名,也可以接受一个对象,实现筛选
  3. 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>

uppercase和lowercase

//Model
$scope.name = 'wSsCat';
//View
<p>{{name|uppercase}}</p>
<p>{{name|lowercase}}</p>

json

json过滤器可以把一个js对象格式化为json字符串,没有参数,作用就和我们熟悉的JSON.stringify()一样,一般用于调试

<p>{{obj|json}}</p>

number

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 精确到就是小数点后几位

Angular内置过滤器

自定义过滤器

app.filter("过滤器名字",function("服务")){
	return function("传入需要处理的值"){
		return "返回处理完的值"
	}
}

Angular自定义关键词检索过滤器

表单验证

value value
$dirty 表单有填写记录
$valid 字段内容合法的
$invalid 字段内容是非法的
$pristine 表单没有填写记录
$error.required 值是必须的

参考Angular表单验证DEMO

路由

UI路由

引入JS文件

开始引入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"}

页面之间通信数据

路由之间通信数据

不同页面之前的控制器之间通信数据

在url上传递和接受(拼接参数到url上,然后用$loacion.search()接受) 思路就如同在路由上配置以下代码

.state('page2',{
	url:'/page2/:id/:name',//参数用:params的形式,多个参数的话用/隔开
	templateUrl:'template/page2.html',
	controller:'page2Ctrl'
})

然后在控制器中用$state服务接受

app.controller("page2Ctrl",function($state){
	$state.params.id
	$state.params.name
})

一个视图多个ui-view

当一个视图拥有多个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'
		}
	}
})

ng路由

1.下载ng路由文件

引入angular-route.js到项目中,放在angular.js之后,然后在代码里面引入ngRoute模块

<script type="text/javascript" src="../js/angular.js"></script>
<script type="text/javascript" src="../js/angular-route.js"></script>

2.包含了ngRoute模块作为主应用模块的依赖模块

angular.module('helloWscatsApp',['ngRoute'])

3.使用ngView指令

<div ng-view></div>
  1. 打开浏览器,定位到需要呈现路由所在的页面,我们在url基础上加#!/路由的名字
url + #!/路由的名字

$routeProvider

两个核心方法when()otherwise()

配置参数 用法
controller function或string类型。在当前模板上执行的controller函数,生成新的scope
controllerAs string类型,为controller指定别名
template string或function类型,视图所用的模板,这部分内容将被ngView引用
templateUrl string或function类型,当视图模板为单独的html文件或是使用了<script type="text/ng-template">定义模板时使用
resolve 指定当前controller所依赖的其他模块
redirectTo 重定向的地址

可以使用$routeProvider用来定义路由规则

module.config(['$routeProvider', function($routeProvider) {
	$routeProvider
		.when('/', {
			template: '他是Oaoafly'
		})
		.when('/wscats', {
			template: '他是Wscats'
		})
		.when('/windiest', {
			template: '她是Windiest'
		})
		.otherwise({
			redirectTo: '/'
		});
}]);

登录注册逻辑

  1. 首先获取用户输入的用户名和密码(ng-model->$scope)
  2. 根据后端给我们提供的接口,把用户输入的信息提交到服务器($http,post)
  3. 用ng-cookie保存后端给我们的token
  4. 判断是否登录状态(自动登录),我们就把token提交服务器作为验证,如果验证成功则继续逻辑,如果失败则返回登录注册页面

angular-tutorial's People

Contributors

wscats avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.