第1章介绍
AngularJS是一款由Google公司开发维护的前端MVC框架,其克服了HTML在构建应用上的诸多不足,从而降低了开发成本提升了开发效率。
1.1 特点
AngularJS与我们之前学习的jQuery是有一定的区别的,jQuery更准确来说只一个类库(类库指的是一系列函数的集合)以DOM做为驱动(核心),而AngularJS则一个框架(诸多类库的集合)以数据和逻辑做为驱动(核心)。
框架对开发的流程和模式做了约束,开发者遵照约束进行开发,更注重的实际的业务逻辑。
AngularJS有着诸多特性,最为核心的是:模块化、双向数据绑定、语义化标签、依赖注入等。
与之类似的框架还有BackBone、KnockoutJS、Vue、React等。
1.2 下载
1、通过AngularJS官网下载,不过由于国内特殊的国情,需要FQ才能访问。
2、通过npm下载,npm install angular
3、通过bower下载,bower install angular
bower是什么?
1.3 体验AngularJS
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS 介绍</title>
<!-- 引入AngularJS 框架 -->
<script src="./libs/angular.min.js"></script>
</head>
<body ng-app>
<input type="text" ng-model="msg">
<h2>你好: {{msg}}</h2>
</body>
</html>
1.4 MVC
MVC是一种开发模式,由模型(Model)、视图(View)、控制器(Controller)3部分构成,采用这种开发模式为合理组织代码提供了方便、降低了代码间的耦合度、功能结构清晰可见。
模型(Model)一般用来处理数据(读取/设置),一般指操作数据库。
视图(View)一般用来展示数据,比如通过HTML展示。
控制器(Controller)一般用做连接模型和视图的桥梁。
通过ThinkPHP来演示后端MVC的执行流程,其重点在于理解。
MVC更多应用在后端开发程序里,后被引入到前端开发中,由于受到前端技术的限制便有了一些细节的调整,进而出现了很多MVC的衍生版(子集)如MVVM、MVW、MVP、MV*等。
注:做为初学可以不必过于在意这些概念。
1.在开发网站中,所有的功能其实都是前端人员发送请求并接受相应,然后将响应的数据放到页面中去。
数据---->页面(对应数据要展示的对应页面),将处理数据的角色,称为模型(Model)。展示数据的角色称为视图(View)。为了保证对应的数据要展示到对应的页面上,需要分配,称为控制器(controller)。
[MVC是一种开发的模式,采用这种开发模式可以使开发变得更加高效。]
2.通过米快画的形式开发,每个模块下包括MVC,使用HTML在构建是变得灵活。
2.1当引入angular.js后会提供一个全局对象angular,在此对象下有若干的方法,其次module方法可以创建模块 var App=angluar.module("App",[]);
2.2每个模块包括MVC,模块实例也是一个对象,在此对象下有若干的方法,其次controller方法创建一个控制器,App.controller('Demo',['$scope',function($scope){}]);$scopr即模型(Model)
2.3视图即HTML,每一个视图都隶属于某一个控制器,通过ng-controller进行指定,ng-controller="Demo"
第2章模块化
使用AngularJS构建应用(App)时是以模块化(Module)的方式组织的,即将整个应用划分成若干模块,每个模块都有各自的职责,最终组合成一个整体。
采用模块化的组织方式,可以最大程度的实现代码的复用,可以像搭积木一样进行开发。
2.1 定义应用
通过为任一HTML标签添加ng-app属性,可以指定一个应用,表示此标签所包裹的内容都属于应用(App)的一部分。
2.2 定义模块
AngularJS提供了一个全局对象angular,在此全局对象下存在若干的方法,其中angular.module()方法用来定义一个模块。
注:应用(App)其本质也是一个模块(一个比较大的模块)。
2.3 定义控制器
控制器(Controller)作为连接模型(Model)和视图(View)的桥梁存在,所以当我们定义好了控制器以后也就定义好了模型和视图。
模型(Model)数据是要展示到视图(View)上的,所以需要将控制器(Controller)关联到视图(View)上,通过为HTML标签添加ng-controller属性并赋值相应的控制器(Controller)的名称,就确立了关联关系。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AnguarJS 模块</title>
<script src="./libs/angular.min.js"></script>
<script>
// 提供一个全局对象 angular
// 在这个对象下有若干方法,可以实现具体功能
// 其中module方法可以创建一个模块
// 需要两个参数,第1个为模块名称,第2个为依赖(目前空数组)
var App = angular.module('App', []);
// 要完成功能还需要MVC
// 上一步创建的模块其返回值App也是一个对象
// 在此对象下又有若干方法,其中controller方法
// 可以创建一个控制器
App.controller('Demo', ['$scope', function ($scope) {
// $scope 是一个空对象{}
// 就是Model
$scope.name = '你好 itcast';
$scope.courses = ['html', 'css', 'js'];
$scope.stars = [
{name: '刘德华', age: 60, sex: '男', area: '香港'},
{name: '王力宏', age: 39, sex: '男', area: '台湾'},
{name: '周杰伦', age: 37, sex: '男', area: '台湾'}
];
}]);
// for(var i=0; i<courses.length; i++) {
// courses[i]
// }
</script>
</head>
<body ng-app="App">
<div class="box" ng-controller="Demo">
<h1>{{name}}</h1>
<ul>
<li ng-repeat="i in courses">{{i}}</li>
</ul>
<table>
<tr>
<td>姓名</td>
<td>性别</td>
<td>年龄</td>
<td>地区</td>
</tr>
<tr ng-repeat="star in stars">
<td>{{star.name}}</td>
<td>{{star.sex}}</td>
<td>{{star.age}}</td>
<td>{{star.area}}</td>
</tr>
</table>
</div>
</body>
</html>
以上步骤就是AngularJS最基本的MVC工作模式。
下图是AngularJS的结构,学习AngularJS会围绕下图的结构展开。
第3章指令
HTML在构建应用(App)时存在诸多不足之处,AngularJS通过扩展一系列的HTML属性或标签来弥补这些缺陷,所谓指令就是AngularJS自定义的HTML属性或标签,这些指令都是以ng-做为前缀的,例如ng-app、ng-controller、ng-repeat等。
3.1 内置指令
ng-app 指定应用根元素,至少有一个元素指定了此属性。
ng-controller 指定控制器
ng-show控制元素是否显示,true显示、false不显示
ng-hide控制元素是否隐藏,true隐藏、false不隐藏
ng-if控制元素是否“存在”,true存在、false不存在
ng-src增强图片路径
ng-href增强地址
ng-class控制类名
ng-include引入模板
ng-disabled表单禁用
ng-readonly表单只读
ng-checked单/复选框表单选中
ng-selected下拉框表单选中
<!DOCTYPE html>
<html lang="en" ng-app="App">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.red {
color: red;
}
.blue {
color: blue;
}
</style>
<script src="./libs/angular.min.js"></script>
</head>
<body>
<!-- <img src="./images/author.jpg" alt=""> -->
<div ng-controller="DemoController">
<link rel="stylesheet" ng-href="{{link}}">
<p ng-show="false">学习使用ng-show指令,当属性值true时显示,否则隐藏</p>
<p ng-hide="0">学习使用ng-hide指令,当属性值true时隐藏,否则显示</p>
<p ng-if="1">学习使用ng-if指令,当属性值true时显示,否则隐藏</p>
<img ng-src="{{path}}" alt="">
<p class="{{color}}">一些文字</p>
<p ng-class="{red: false, blue: true}">另一些文字</p>
<form action="">
<ul>
<li>
姓名:<input type="text" value="itcast" ng-disabled="false">
</li>
<li>
地区:<input type="text" value="河北省" ng-readonly="true">
</li>
<li>爱好: 写代码<input type="checkbox" ng-checked="false"></li>
<li>科目:
<select name="" id="">
<option value="0">PHP</option>
<option value="0" ng-selected="false">前端</option>
<option value="0">UI</option>
</select>
</li>
</ul>
</form>
</div>
<script>
// ng-app 指定一个应用
// 可以用应用任意标签上,并且将此标签包括区
// 视为一个应用的范围
// 一个页面可以有多个但是不能进行嵌套,一般指定一个
var App = angular.module('App', []);
// ng-controller 指定某视图隶属于某一个控制器
App.controller('DemoController', ['$scope', function ($scope) {
$scope.path = './images/author.jpg';
$scope.link = './css/base.css';
$scope.color = 'red';
}]);
</script>
</body>
</html>
注:后续学习过程中还会介绍其它指令。
3.2 自定义指令
AngularJS允许根据实际业务需要自定义指令,通过angular全局对象下的directive方法实现。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS 自定义指令</title>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('Demo', []);
// 自定义控制器
App.controller('ItcastController', ['$scope', function ($scope) {
$scope.list = ['html', 'css', 'js'];
}]);
// 自定义指令
// 第一个参数,指令的名称
// 第二个参数,回调函数
App.directive('itcast', function () {
// 此回调函数指定具体指令应该做哪些事情
// 通过一个对象来定义
var obj = {
// 自定义指令可以是属性可以是标签
// E element
// A attribute
// C class
// M mark
restrict: 'ECMA',
// 所有内容必须包含在一个根元素下
template: '<div><h1>你好, AngularJS!</h1><p>哈哈</p></div>',
// templateUrl: './header.html',
replace: true,
// scope: {},
// link: function () {},
// compile: function () {}
}
return obj;
});
</script>
</head>
<body ng-app="Demo">
<div itcast></div>
<itcast></itcast>
<div class="itcast"></div>
<!-- directive:itcast -->
<ul ng-controller="ItcastController">
<li ng-repeat="item in list">{{item}}</li>
</ul>
</body>
</html>
第4章数据绑定
AngularJS是以数据做为驱动的MVC框架,所有模型(Model)里的数据经由控制器(Controller)展示到视图(View)中。
所谓数据绑定指的就是将模型(Model)中的数据与相应的视图(View)进行关联,分为单向绑定和双向绑定两种方式。
4.1 单向绑定
单向数据绑定是指将模型(Model)数据,按着写好的视图(View)模板生成HTML标签,然后追加到DOM中显示,如之前所学的artTemplate 模板引擎的工作方式。
如下图所示,只能模型(Model)数据向视图(View)传递。
4.2 双向绑定
双向绑定则可以实现模型(Model)数据和视图(View)模板的双向传递,如下图所示。
4.3 相关指令
在AngularJS中通过“{{}}”和ng-bind指令来实现模型(Model)数据向视图模板(View)的绑定,模型数据通过一个内置服务$scope来提供,这个$scope是一个空对象,通过为这个对象添加属性或者方法便可以在相应的视图(View)模板里被访问。
注:“{{}}”是ng-bind的简写形式,其区别在于通过“{{}}”绑定数据时会有“闪烁”现象,添加ng-cloak也可以解决“闪烁”现象,通过ng-bind-template可以绑定多个数据。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS 数据绑定</title>
<script src="./libs/angular.min.js"></script>
</head>
<body ng-app="Demo">
<div class="box" ng-controller="DemoController">
<!-- <h1 ng-cloak>{{name}}<small ng-bind="age"></small></h1> -->
<!-- <h1>{{name}}{{age}}</h1> -->
<h1 ng-bind-template="{{name}}{{age}}"></h1>
<ul>
<li ng-repeat="course in courses">{{course}}</li>
</ul>
</div>
<script>
var App = angular.module('Demo', []);
App.controller('DemoController', ['$scope', function ($scope) {
$scope.name = '小明';
$scope.age = '18';
$scope.courses = ['html', 'css', 'js'];
}]);
</script>
</body>
</html>
通过为表单元素添加ng-model指令实现视图(View)模板向模型(Model)数据的绑定。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS 数据绑定</title>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
App.controller('DemoController', ['$scope', function ($scope) {
$scope.msg = '你好!!!!!';
$scope.testmsg = '';
$scope.show = function () {
// 可以输出模型数据
alert($scope.msg);
// alert($scope.testmsg);
}
}]);
</script>
</head>
<body ng-app="App">
<div ng-controller="DemoController">
<h3>{{msg}}</h3>
<input type="text" ng-model="testmsg">
<h4>{{testmsg}}</h4>
<button ng-click="show()">显示</button>
</div>
</body>
</html>
通过ng-init可以初始化模型(Model)也就是$scope。
<!DOCTYPE html>
<html lang="en" ng-app="App">
<head>
<meta charset="UTF-8">
<title>AngularJS 数据绑定</title>
</head>
<body>
<div ng-controller="DemoController" ng-init="name='小明'; age=18">
<h1>{{name}}</h1>
<small>{{age}}</small>
</div>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
App.controller('DemoController', ['$scope', function ($scope) {
// $scope.name = "小明";
}]);
</script>
</body>
</html>
AngularJS对事件也进行了扩展,无需显式的获取DOM元素便可以添加事件,易用性变的更强。通过在原有事件名称基础上添加ng-做为前缀,然后以属性的形式添加到相应的HTML标签上即可。如ng-click、ng-dblclick、ng-blur等。
<!DOCTYPE html>
<html lang="en" ng-app="App">
<head>
<meta charset="UTF-8">
<title>AngularJS 数据绑定</title>
<style>
ul {
list-style: none;
}
.mouseover {
width: 100px;
height: 100px;
background-color: pink;
}
</style>
</head>
<body>
<div ng-controller="DemoController">
<ul>
<li>{{name}}</li>
<li><button ng-click="myclick()">点击</button></li>
<li class="mouseover" ng-mouseout="mymouseout()" ng-mouseover="mymouseover()"></li>
<li><input type="text" ng-keydown="mykeydown()"></li>
</ul>
</div>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
App.controller('DemoController', ['$scope', function ($scope) {
$scope.name = '小明';
$scope.myclick = function () {
alert('点击了一下?');
}
$scope.mymouseover = function () {
console.log('鼠标经过过?');
}
$scope.mymouseout = function () {
console.log('鼠标离开了?');
}
$scope.mykeydown = function () {
console.log('按键被按下');
}
}]);
</script>
</body>
</html>
通过ng-repeat可以将数组或对象数据迭代到视图模板中,ng-switch、on、ng-switch-when可以对数据进行筛选。
<!DOCTYPE html>
<html lang="en" ng-app="App">
<head>
<meta charset="UTF-8">
<title>AngularJS 数据绑定</title>
</head>
<body>
<div ng-controller="DemoController">
<ul>
<li ng-repeat="val in obj">{{val}}</li>
</ul>
<ul>
<li ng-repeat="val in courses" ng-switch on="val">
<span ng-switch-when="css">{{val}}</span>
</li>
</ul>
</div>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
App.controller('DemoController', ['$scope', function ($scope) {
$scope.obj = {
name: '小明',
age: 18
}
$scope.courses = ['html', 'css', 'js'];
}]);
var arr = ['html', 'css', 'js'];
for(var i=0; i<arr.length; i++) {
if(arr[i] == 'css') {
console.log(arr[i])
}
}
// switch($str) {
// case 'css':
// console.log($str);
// break;
// case 'js'
// }
</script>
</body>
</html>
![数据绑定.png](https://i-blog.csdnimg.cn/blog_migrate/5823c7eed4a052f921f60a979bede21c.png)
第5章作用域
通常AngularJS中应用(App)是由若干个视图(View)组合成而成的,而视图(View)又都是HTML元素,并且HTML元素是可以互相嵌套的,另一方面视图都隶属于某个控制器(Controller),进而控制器之间也必然会产生嵌套关系。
每个控制器(Controller)又都对应一个模型(Model)也就是$scope对象,不同层级控制器(Controller)下的$scope便产生了作用域。
5.1 根作用域
一个AngularJS的应用(App)在启动时会自动创建一个根作用域$rootScope,这个根作用域在整个应用范围(ng-app所在标签以内)都是可以被访问到的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
//
App.controller('ParentController', ['$scope', function ($scope) {
// $scope.name = '康熙';
}]);
App.controller('ChildController', ['$scope', function ($scope) {
// $scope.name = '雍正';
}]);
var a = 10;
function fn() {
// a = 15;
alert(a);
function bar() {
// a = 20;
alert(a);
}
bar();
}
fn();
</script>
</head>
<body>
<div class="box" ng-app="App" ng-init="name='顺治'">
<div class="parent" ng-controller="ParentController">
<dl>
<dt>{{name}}</dt>
<dd></dd>
</dl>
<div class="child" ng-controller="ChildController">
<dl>
<dt>---{{name}}</dt>
<dd></dd>
</dl>
</div>
</div>
</div>
</body>
</html>
5.2 子作用域
通过ng-controller指令可以创建一个子作用域,新建的作用域可以访问其父作用域的数据。
第6章过滤器
在AngularJS中使用过滤器格式化展示数据,在“{{}}”中使用“|”来调用过滤器,使用“:”传递参数。
6.1 内置过滤器
1、currency将数值格式化为货币格式
2、date日期格式化,年(y)、月(M)、日(d)、星期(EEEE/EEE)、时(H/h)、分(m)、秒(s)、毫秒(.sss),也可以组合到一起使用。
3、filter在给定数组中选择满足条件的一个子集,并返回一个新数组,其条件可以是一个字符串、对象、函数
4、json将Javascrip对象转成JSON字符串。
5、limitTo取出字符串或数组的前(正数)几位或后(负数)几位
6、lowercase将文本转换成小写格式
7、uppercase将文本转换成大写格式
8、number数字格式化,可控制小位位数
9、orderBy对数组进行排序,第2个参数可控制方向
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS 过滤器</title>
</head>
<body ng-app="App">
<ul ng-controller="DemoController">
<li>当前时间为: {{now|date:'y-M-d hh:mm:ss'}}</li>
<li>商品价格: {{price|currency:'¥':4}}</li>
<li>你叫啥: {{desc|uppercase}}</li>
<li>年龄: {{age|lowercase}}</li>
<li>数值: {{num|number:3}}</li>
<li>转JSON: {{obj|json}}</li>
<li>截取: {{desc|limitTo:-4}}</li>
<li>截取: {{items|limitTo:2:3}}</li>
<li>排序: {{students|orderBy:'score':false}}</li>
<li>过滤: {{students|filter:'小明'}}</li>
<li>过滤: {{students|filter:{name:'小牛'} }}</li>
<li>过滤: {{courses|filter: 'p'}}</li>
</ul>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
App.controller('DemoController', ['$scope', function ($scope) {
$scope.now = new Date;
$scope.price = 12.345;
$scope.desc = 'my name is xiaoming';
$scope.age = 'HOw Old are you?';
$scope.num = 123.4567;
$scope.obj = {name: '小明', age: 18};
$scope.items = ['html', 'css', 'js', 'php', 'java'];
$scope.students = [
{name: '小明', age: 18, score: 99},
{name: '小红', age: 16, score: 96},
{name: '小牛', age: 19, score: 97}
];
$scope.courses = ['php', 'java', 'javascript', 'photoshop'];
}])
</script>
</body>
</html>
6.2 自定义过滤器
除了使用AngularJS内建过滤器外,还可以根业务需要自定义过滤器,通过模块对象实例提供的filter方法自定义过滤器。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS 自定义过滤器</title>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
// 定义控制器
App.controller('DemoController', ['$scope', function ($scope) {
$scope.str = '测试内容';
$scope.price = 12.345;
$scope.desc = 'my name is laozhao';
}]);
// 定义指令
// App.directive();
// 定义过滤器
// 过滤器本质就一个函数
// 第1个参数为过滤器名称(函数名称)
// 第2个参数为回调函数
App.filter('demo', function () {
// 在此定义过滤器具体的功能
// function abc() {
// console.log('1111');
// }
// return abc;
return function (arg, type, fixed) {
// return arg + arg2 + arg3;
return type + arg.toFixed(fixed);
}
});
// 自定义一个实英文首字母大定的过滤器
App.filter('capitalize', function () {
return function (input) {
console.log(input);
return input[0].toUpperCase() + input.slice(1);
}
});
</script>
</head>
<body ng-app="App">
<div ng-controller="DemoController">
<dl>
<dt>自定义过滤器</dt>
<dd>{{price|demo:'¥':2}}</dd>
<dd>{{desc|capitalize}}</dd>
</dl>
</div>
</body>
</html>
第7章依赖注入
AngularJS采用模块化的方式组织代码,将一些通用逻辑封装成一个对象或函数,实现最大程度的复用,这导致了使用者和被使用者之间存在依赖关系。
所谓依赖注入是指在运行时自动查找依赖关系,然后将查找到依赖传递给使用者的一种机制。
常见的AngularJS内置服务有$http、$location、$timeout、$rootScope等
7.1 推断式注入
没有明确声明依赖,AngularJS会将函数参数名称当成是依赖的名称。
这种方式会带来一个问题,当代码经过压缩后函数的参数被压缩,这样便会造成依赖无法找到。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS 依赖注入</title>
</head>
<body ng-app="App">
<div class="box" ng-controller="DemoController">
<h1>{{name}}</h1>
</div>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
// AngularJS 内置一些具有特殊功能的“模块”
// 开发者在开发的时候可以直接使用这些“模块”
App.controller('DemoController', function ($scope, $http) {
$scope.name = '推断式';
});
</script>
</body>
</html>
7.2 行内注入
以数组形式明确声明依赖,数组元素都是包含依赖名称的字符串,数组最后一个元素是依赖注入的目标函数。
推荐使用这种方式声明依赖
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS 依赖注入</title>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
// 写一个控制器
// $scope 就是AngularJS 事件提供供的一个功能模块
// 数组是用来声明需要依赖哪些功能模块的
// 数组最后一个单元必须为函数,函数的参数即注入
// angularJS将查找得到的功能模块以参数的形式传入
// 最后一个数组单元传递的函数,这个过程称为注入
// 行内式依赖注入
App.controller('DemoController', ['$scope', '$http', '$rootScope', function ($scope, $http, $rootScope) {
$scope.name = '依赖注入';
}]);
// 依赖注入并非只能用于定义控制器时,
// 只是我们目前接触控制器最多,拿它举例说明
</script>
</head>
<body ng-app="App">
<div ng-controller="DemoController">
<h1>{{name}}</h1>
</div>
</body>
</html>
第8章服务
服务是一个对象或函数,对外提供特定的功能。
8.1 内建服务
1、$location是对原生Javascript中location对象属性和方法的封装。
$location是关于链接的操作,hash是特殊的,#号后面的都封装成hash了,方便调用别的方法。
<!DOCTYPE html>
<html lang="en" ng-app="App">
<head>
<meta charset="UTF-8">
<title>AngularJS 服务</title>
</head>
<body>
<dl ng-controller="DemoController">
<dt>$location服务</dt>
<a href="#/abc?name=itcast&age=10#hash">地址</a>
<dd>absUrl: {{absUrl}}</dd>
<dd>host: {{host}}</dd>
<dd>port: {{port}}</dd>
<dd>hash: {{hash}}</dd>
<dd>search: {{search}}</dd>
<dd>protocol: {{protocol}}</dd>
</dl>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
// $location内置服务
// AngularJS 专门提供了一个帮助获取URL地址一个服务
App.controller('DemoController', ['$scope', '$location', function ($scope, $location) {
console.log($location);
// 获取绝对路径
$scope.absUrl = $location.absUrl();
$scope.host = $location.host();
$scope.port = $location.port();
// angularjs 对hash做了特别的处理
$scope.hash = $location.hash();
$scope.search = $location.search();
$scope.protocol = $location.protocol();
}]);
// 一个完整地址是包括若干部分的
// http://www.baidu.com:80
// http://localhost/02day/4-code/$http.html
// http://localhost/02day/4-code/$http.html?name=小明&age=10
// http://localhost/02day/4-code/$http.html#demo
// http 表示协议
// localhost/127.0.0.1/www.baidu.com 表示主机
// 80 表示端口号
// # 表示锚链接
// ? 表示查询参数或叫queryString
// 02day/4-code 表示pathname
// js BOM 提供了一个对象 location 可以获取地址的任一部分
for(var key in location) {
console.log(key + '~~~' + location[key]);
}
</script>
</body>
</html>
2、$timeout&$interval对原生Javascript中的setTimeout和setInterval进行了封装。
$timeout是等待多久后执行,$interval是间歇执行。
清除定时器:$interval.cancel(interval赋值的变量)。
<!DOCTYPE html>
<html lang="en" ng-app="App">
<head>
<meta charset="UTF-8">
<title>AngularJS 服务</title>
</head>
<body>
<div ng-controller="DemoController">
<ul>
<li>{{msg}}</li>
<li>{{count}}</li>
<li>{{now|date:'yyyy-MM-dd hh:mm:ss'}}</li>
<li><button ng-click="start()">开始计时</button></li>
<li><button ng-click="stop()">停止计时</button></li>
</ul>
</div>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
// $timeout 和 $interval
App.controller('DemoController', ['$scope', '$timeout', '$interval',function ($scope, $timeout, $interval) {
// $timeout(function () {
// $scope.msg = '我在1秒后显示';
// }, 1000);
// var count = 0;
// $interval(function () {
// $scope.count = count++;
// }, 500);
var timer;
$scope.start = function () {
timer = $interval(function () {
$scope.now = new Date;
}, 1000);
}
$scope.stop = function () {
// 清
$interval.cancel(timer);
}
}])
</script>
</body>
</html>
3、$filter过滤器在控制器中格式化数据,用来处理数据格式的。
<!DOCTYPE html>
<html lang="en" ng-app="App">
<head>
<meta charset="UTF-8">
<title>AngularJS 服务</title>
</head>
<body>
<ul ng-controller="DemoController">
<li>价格: {{price}}</li>
<li>大写: {{intro}}</li>
<li>截取: {{list}}</li>
</ul>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
// 前面学习过滤器,主要应用在{{}}中
// 但是也会有需求,在控制器中使用,这时需要用到一个
// 叫$filter的服务
// $filter是过滤器
App.controller('DemoController', ['$scope', '$filter', function ($scope, $filter) {
// $filter服务仍然是处理数据格式的
var price = 12.345; // ¥12.345;
var currency = $filter('currency');
$scope.price = currency(price, '¥', 3);
var intro = 'my name is laozhao';
var uppercase = $filter('uppercase');
$scope.intro = uppercase(intro);
var list = ['html', 'css', 'js'];
var limitTo = $filter('limitTo');
$scope.list = limitTo(list, 2);
}])
</script>
</body>
</html>
4、$log打印调试信息
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS 服务</title>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
// $scope是一个具有特定功能的模块
// 在AngularJS中将具有特定功能的模块称为服务
App.controller('DemoController', ['$scope', '$log', function ($scope, $log) {
// $scope 是一个AngularJS内置服务,可以充当模型这个角色
$scope.name = '小明';
// $log是一个内置的服务,可以帮助开发者在开发阶段进行调试
$log.debug('调试信息');
$log.info('信息');
$log.log('打印');
$log.error('错误');
$log.warn('警告');
}]);
</script>
</head>
<body ng-app="App">
<div ng-controller="DemoController">
<h1>{{name}}</h1>
</div>
</body>
</html>
5、$http用于向服务端发起异步请求。
同时还支持多种快捷方式如$http.get()、$http.post()、$http.jsonp。
注:各参数含义见代码注释。
GET:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS $http服务</title>
</head>
<body ng-app="App">
<div ng-controller="DemoController">
<h1>练习$http</h1>
</div>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
App.controller('DemoController', ['$http', '$log', function ($http, $log) {
// $http 是angularJS内置服务,可以向服务器发起异步请求
$http({
url: './example.php', // 请求地址
method: 'get', // 请求方式
params: {sex: '男'}, // 专门用来传递get形式的参数
// AngularJS 以get形式传参时,并没有使用data
data: 'name=小明&age=10' // 专门用来传post形式的参数
}).success(function (info) { // 响应成功后会执行
// info 即服务端返回的数据
$log.info(info);
});
}]);
// XMLHttpRequest
// var xhr = new XMLHttpRequest;
// xhr.open('post', './example.php');
// xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// 之所以在jQuery可以通data以对象形式传递参数
// 是因jQuery内部进行处理(key=val&key1=val1)
// 之所以在jQuery中传递参数不论get或post都可以使用
// data传递,是因为在jQuery内部做了判断将参数放到不同位置了
// 标准格式 key=val&key1=val1
// xhr.send('name=小明&age=10');
// $.ajax({
// url: './example.php',
// type: 'post',
// data: {name: 'itcast', age: 10}
// })
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS $http服务</title>
</head>
<body ng-app="App">
<div ng-controller="DemoController">
<h1>练习$http</h1>
</div>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
App.controller('DemoController', ['$http', '$log', function ($http, $log) {
// $http 是angularJS内置服务,可以向服务器发起异步请求
$http({
url: './example.php', // 请求地址
method: 'post', // 请求方式
// angularJS没有将一个对象数据转换成
// key=val&key1=val1
// data: {name: '小明', age: 18}, // 传递参数
data: 'name=小明&age=10',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).success(function (info) { // 响应成功后会执行
// info 即服务端返回的数据
$log.info(info);
});
}]);
// XMLHttpRequest
// var xhr = new XMLHttpRequest;
// xhr.open('post', './example.php');
// xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// 之所以在jQuery可以通data以对象形式传递参数
// 是因jQuery内部进行处理(key=val&key1=val1)
// 标准格式 key=val&key1=val1
// xhr.send('name=小明&age=10');
// $.ajax({
// url: './example.php',
// type: 'post',
// data: {name: 'itcast', age: 10}
// })
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS $http服务</title>
</head>
<body ng-app="App">
<div ng-controller="DemoController">
<h1>练习$http</h1>
</div>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
App.controller('DemoController', ['$http', '$log', function ($http, $log) {
$http({
url: './jsonp.php',
method: 'jsonp', // 使用JSONP请求
// JSON原理中需要将前端“事先”定义好的一个函数名
// 传递给后端,后在返回这个函数调用(函数名())
// 并且在调用时传递一个实参,通过这种方式可以间接
// 获取服务端数据
// 类似这种格式值angular.callbacks._0被添加到了
// 请求后面,angular.callbacks._0就是angularjs事先定义好的一个函数名字
// angular.callbacks._0();
params: {callback: 'JSON_CALLBACK'}
}).success(function (info) {
$log.info(info);
});
// $.ajax({
// url: '',
// dataType: 'jsonp',
// success: function (info) {
// }
// });
}]);
</script>
</body>
</html>
8.2 自定义服务
通过上面例子得知,所谓服务是将一些通用性的功能逻辑进行封装方便使用,AngularJS允许将自定义服务。
1、factory方法
<!DOCTYPE html>
<html lang="en" ng-app="App">
<head>
<meta charset="UTF-8">
<title>AngularJS 自定义服务</title>
</head>
<body>
<div ng-controller="DemoController">
<span>{{now}}</span>
<button ng-click="show()">显示时间</button>
</div>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
// App.directive(); 自定义指令
// App.filter(); 自定义过滤器
// App.controller(); “自定义”控制器
// App.factory(); 自定义服务
// 定义一个名叫showTime的服务
App.factory('showTime', ['$filter', function ($filter) {
function show() {
// 当外部调用show方法时
// 将结果返回
return $filter('date')(new Date, 'yyyy-MM-dd hh:mm:ss');
}
// 将封装好的服务返回,供外部使用
// 可以以对象形式也可以直接返回函数
// return show
// 或者
return {
show: show
}
}]);
// 定义一个控制器,将自定义的服务注入进来
// 测试
App.controller('DemoController', ['$scope', 'showTime', function ($scope, showTime) {
// showTime就是自定义的服务
$scope.show = function () {
// 当我们自定义的服务返回一个对象时
// 使用 showTime.show()
// $scope.now = showTime.show();
// 当我们自定义的服务直接返回函数时
// 使用showTime();
$scope.now = showTime();
};
}]);
</script>
</body>
</html>
2、service方法
<!DOCTYPE html>
<html lang="en" ng-app="App">
<head>
<meta charset="UTF-8">
<title>AngularJS 自定义服务</title>
</head>
<body>
<div ng-controller="DemoController">
<h1>{{now}}</h1>
</div>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
// 自定义服务
// 通过 servie定义一个服务
// 第1个参数是自定义服务名称
// 第2个参数是依赖注入
App.service('showTime', ['$filter', function ($filter) {
// 将定义好的服务添加到this对象上
// 外部就可以使用了
// $filter可以直接拿来用
this.show = function (format) {
return $filter('date')(new Date, format);
}
}]);
// 自定义一个控制器,测试自定义服务
App.controller('DemoController', ['$scope', 'showTime', function ($scope, showTime) {
$scope.now = showTime.show('MM');
}])
</script>
</body>
</html>
3、value方法定义常量
<!DOCTYPE html>
<html lang="en" ng-app="App">
<head>
<meta charset="UTF-8">
<title>AngularJS 自定义服务</title>
</head>
<body>
<div ng-controller="DemoController">
{{author}}
{{version}}
</div>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
// 自定义常量服务
App.value('author', 'itcast');
App.value('version', '1.0');
// 本质上一个服务
// 从表现形式上是一个常量
// 常量就是不变的值与变对量相对应
// 声明依赖调用服务
App.controller('DemoController', ['$scope', 'author', 'version', function ($scope, author, version) {
$scope.author = author;
$scope.version = version;
}])
</script>
</body>
</html>
在介绍服务时曾提到服务本质就是一个对象或函数,所以自定义服务就是要返回一个对象或函数以供使用。
第9章模块加载
AngularJS模块可以在被加载或者执行之前对其自身进行配置。我们可以在应用的加载阶段配置不同的逻辑。
9.1 配置块
1、通过config方法实现对模块的配置,AngularJS中的服务大部分都对应一个“provider”,用来执行与对应服务相同的功能或对其进行配置。
比如$log、$http、$location都是内置服务,相对应的“provider”分别是$logProvider、$httpProvider、$locationPorvider。
下图以$log为例进行演示,修改了配置
下图以$filter为例进行演示,实现相同功能
<!DOCTYPE html>
<html lang="en" ng-app="App">
<head>
<meta charset="UTF-8">
<title>AngularJS 服务</title>
</head>
<body>
<ul ng-controller="DemoController">
<li>价格: {{price}}</li>
<li>大写: {{intro}}</li>
<li>截取: {{list}}</li>
</ul>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
// 前面学习过滤器,主要应用在{{}}中
// 但是也会有需求,在控制器中使用,这时需要用到一个
// 叫$filter的服务
// $filter是过滤器
App.controller('DemoController', ['$scope', '$filter', function ($scope, $filter) {
// $filter服务仍然是处理数据格式的
var price = 12.345; // ¥12.345;
var currency = $filter('currency');
$scope.price = currency(price, '¥', 3);
var intro = 'my name is laozhao';
var uppercase = $filter('uppercase');
$scope.intro = uppercase(intro);
var list = ['html', 'css', 'js'];
var limitTo = $filter('limitTo');
$scope.list = limitTo(list, 2);
}])
</script>
</body>
</html>
9.2 运行块
服务也是模块形式存在的对且对外提供特定功能,前面学习中都是将服务做为依赖注入进去的,然后再进行调用,除了这种方式外我们也可以直接运行相应的服务模块,AngularJS提供了run方法来实现。
rootScope根作用域(相当于window)
不但如此,run方法还是最先执行的,利用这个特点我们可以将一些需要优先执行的功能通过run方法来运行,比如验证用户是否登录,未登录则不允许进行任何其它操作。
<!DOCTYPE html>
<html lang="en" ng-app="App" ng-init="name='顺治'">
<head>
<meta charset="UTF-8">
<title>AngularJS 模块加载</title>
</head>
<body>
<div ng-controller="DemoController">
{{name}}
{{age}}
</div>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
// 在AngularJS中某些模块是可以直接运行的
// 使用 App.run()
// 例如直接运行$http、$rootScope服务
// $rootScope根作域(相当于window)
App.run(['$http', '$rootScope', function ($http, $rootScope) {
// 定义全局作用域
$rootScope.name = '顺治';
$rootScope.age = '28';
// 利用$http发送异步请求
$http({
url: './example.php'
}).success(function (info) {
console.log(info);
});
}]);
// 定义制器测试全局作用域
App.controller('DemoController', ['$scope', function ($scope) {
// $scope.name = '康熙';
}])
</script>
</body>
</html>
注:此知识点意在了解AngularJS的加载机制。
第10章路由
一个应用是由若个视图组合而成的,根据不同的业务逻辑展示给用户不同的视图,路由则是实现这一功能的关键。
10.1 SPA
SPA(Single Page Application)指的是通单一页面展示所有功能,通过Ajax动态获取数据然后进行实时渲染,结合CSS3动画模仿原生App交互,然后再进行打包(使用工具把Web应用包一个壳,这个壳本质上是浏览器)变成一个“原生”应用。
在PC端也有广泛的应用,通常情况下使用Ajax异步请求数据,然后实现内容局部刷新,局部刷新的本质是动态生成DOM,新生成的DOM元素并没有真实存在于文档中,所以当再次刷新页面时新添加的DOM元素会“丢失”,通过单页面应可以很好的解决这个问题。
10.2 路由(约等于地址)前端路由就是封装了锚链接
在后端开发中通过URL地址可以实现页面(视图)的切换,但是AngularJS是一个纯前端MVC框架,在开发单页面应用时,所有功能都在同一页面完成,所以无需切换URL地址(即不允许产生跳转),但Web应用中又经常通过链接(a标签)来更新页面(视图),当点击链接时还要阻止其向服务器发起请求,通过锚点(页内跳转)可以实现这一点。
实现单页面应用需要具备:
a、只有一页面
b、链接使用锚点
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS 路由和多视图</title>
<style>
body {
padding: 0;
margin: 0;
background-color: #F7F7F7;
font-family: Arial;
}
.wrapper {
width: 980px;
margin: 50px auto;
}
ul {
padding: 0;
margin: 0;
overflow: hidden;
list-style: none;
background-color: #000;
border-radius: 4px;
}
li {
float: left;
width: 120px;
height: 40px;
text-align: center;
line-height: 40px;
font-size: 18px;
}
li.active {
background-color: #333;
}
li a {
display: block;
color: #FFF;
text-decoration: none;
}
.content {
margin-top: 30px;
font-size: 24px;
padding: 0 20px;
}
</style>
</head>
<body ng-app="App">
<div class="wrapper">
<!-- 导航菜单 -->
<ul>
<li class="active">
<a href="#/index">Index</a>
</li>
<li>
<a href="#/introduce">Introduce</a>
</li>
<li>
<a href="#/contact">Contact Us</a>
</li>
</ul>
<!-- 内容 -->
<div class="content">
<!-- 占位符 -->
<div ng-view></div>
</div>
</div>
<!-- 引入核心框架 -->
<script src="./libs/angular.min.js"></script>
<!-- 引入路由模块 -->
<script src="./libs/angular-route.js"></script>
<script>
var App = angular.module('App', ['ngRoute']);
// 就可以使用路由模块了
// 路由模块需要经过一系列配置才可以使用
// $routeProvider
App.config(['$routeProvider', function ($routeProvider) {
// 第1个参数路由的变化
// 第2个参数当前路由的具体逻辑
$routeProvider.when('/index', {
template: '<h1>Index Page!</h1>'
}).when('/introduce', {
template: '<h1>Introduce Page!</h1>'
}).when('/contact', {
template: '<h1>Contact Us Page!</h1>'
}).when('/404', {
template: '<h1 style="color:red;">Not Found</h1>'
})
.otherwise({
redirectTo: '/404'
});
}]);
</script>
</body>
</html>
通过上面的例子发现在单一页面中可以能过hashchange事件监听到锚点的变化,进而可以实现为不同的锚点准不同的视图,单页面应用就是基于这一原理实现的。
AngularJS对这一实现原理进行了封装,将锚点的变化封装成路由(Route),这是与后端路由的根本区别。
在1.2版前路由功能是包含在AngularJS核心代码当中,之后的版本将路由功能独立成一个模块,下载angular-route.js
要实现更新数据,需要发送请求找服务器要,当锚点发送改变后再要数据,使用hashchange事件,添加给window对象,这个事件会在锚点发生改变的时候触发
window.addEventListener('hashchangge',function(){
});
10.2.1 使用
1、引入angular-route.js
2、实例化模块(App)时,当成依赖传进去(模块名称叫ngRoute)。
3、配置路由模块
4、布局模板
通过ng-view指令布局模板,路由匹配的视图会被加载渲染到些区域。
10.2.1 路由参数
1、提供两个方法匹配路由,分别是when和otherwise,when方法需要两个参数,otherwise方法做为when方法的补充只需要一个参数,其中when方法可以被多次调用。
2、第1个参数是一个字符串,代表当前URL中的hash值。
3、第2个参数是一个对象,配置当前路由的参数,如视图、控制器等。
a、template 字符串形式的视图模板
b、templateUrl 引入外部视图模板
c、controller 视图模板所属的控制器
d、redirectTo跳转到其它路由
4、获取参数,在控制中注入$routeParams可以获取传递的参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS 路由和多视图</title>
<style>
body {
padding: 0;
margin: 0;
background-color: #F7F7F7;
font-family: Arial;
}
.wrapper {
width: 980px;
margin: 50px auto;
}
ul {
padding: 0;
margin: 0;
overflow: hidden;
list-style: none;
background-color: #000;
border-radius: 4px;
}
li {
float: left;
width: 120px;
height: 40px;
text-align: center;
line-height: 40px;
font-size: 18px;
}
li.active {
background-color: #333;
}
li a {
display: block;
color: #FFF;
text-decoration: none;
}
.content {
margin-top: 30px;
font-size: 24px;
padding: 0 20px;
}
</style>
</head>
<body ng-app="App">
<div class="wrapper">
<!-- 导航菜单 -->
<ul>
<li class="active">
<a href="#/index">Index</a>
</li>
<li>
<a href="#/introduce">Introduce</a>
</li>
<li>
<a href="#/contact">Contact Us</a>
</li>
</ul>
<!-- 内容 -->
<div class="content">
<!-- 占位符 -->
<div ng-view></div>
</div>
</div>
<!-- 引入核心框架 -->
<script src="./libs/angular.min.js"></script>
<!-- 引入路由模块 -->
<script src="./libs/angular-route.js"></script>
<script>
var App = angular.module('App', ['ngRoute']);
App.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/index', {
// 引入外部视图模板
templateUrl: './views/index.tpl',
// 为引入的视图模板指定控制器
controller: 'IndexController'
}).when('/introduce', {
templateUrl: './views/introduce.html'
}).when('/contact', {
templateUrl: './views/concat.tpl'
})
}])
// 定义控制器
App.controller('IndexController', ['$scope', '$http', function ($scope, $http) {
// $http({
// url: ''
// }).success(function (info) {
// $scope.info = info;
// });
// 添加数据
$scope.course = [
{name: 'HTML', level: '初级', days: '10天'},
{name: 'CSS', level: '初级', days: '12天'},
{name: 'JAVASCRIPT', level: '高级', days: '18天'},
]
}]);
// 后缀是通知操作系统应该使用哪个应用程序将它打开
</script>
</body>
</html>
第11章其它
11.1 jQuery
在没有引入jQuery的前提下AngularJS实现了简版的jQuery Lite,通过angular.element不能选择元素,但可以将一个DOM元素转成jQuery对象,如果引提前引入了jQuery则angular.element则完全等于jQuery。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS jqLite</title>
<style>
.box {
width: 200px;
height: 200px;
border: 1px solid #CCC;
}
</style>
</head>
<body ng-app="App">
<div class="box">有一些文字</div>
<script src="./libs/jquery.min.js"></script>
<script src="./libs/angular.min.js"></script>
<script>
var App = angular.module('App', []);
// 类似于 $('.box').css('color', 'red');
// $('div')
// jQuery 也可将一个原生DOM对象转成jQuery对象
// angular.element() 接收的一个原生DOM对象
// 会将这个原生DOM对象转成jQuery对象
var box = document.querySelector('.box');
angular.element(box).css('color', 'red');
angular.element(box).animate({
width: 400,
height: 400
}, 600);
</script>
</body>
</html>
11.2 bower
基于NodeJS的一个静态资源管理工具,由twitter公司开发维,解决大型网站中静态资源的依赖问题。
1、依赖NodeJS环境和git工具。
2、npm install -g bower安装bower
3、bower search 查找资源信息
4、bower install 安装(下载)资源,通过#号可以指定版本号
5、bower info 查看资源信息
6、bower uninstall 卸载(删除)资源
7、bower init初始化,用来记录资源信息及依赖。
bower可以管理静态资源,并解决依赖关系。bower是基于nodejs的一个工具(使用nodejs开发的),要使用bower需要安装nodejs环境
nodejs就是一个软件,(普通安装即可)。避免安装在中文目录下。
安装完成后,并不会在桌面上创建图标,任务栏也不会有,只可以通过命令行来使用nodejs。
win+r 输入cmd 进入命令管理窗口。
输入 node -v验证nodejs是否正常 -前面有一个空格,显示版本号就是正常。
再输入 npm -v验证npm是否正常