教程推荐位置:http://www.angularjs.net.cn/tutorial/
本人是比较倾向《angular权威教程》和angular手册结合的方式学习。
调试工具极力推荐:ng-inspector
1、数据绑定
angular数据绑定的两个方式:(1)ng-bind指令(2)差值表达式(3)ng-model双向数据绑定
ng-bind和差值表达式都可以写简单的js表达式,ng-model只能绑定变量名。
ng-bind 和 ng-cloak 可以回避闪烁问题(插值表达式在刚刚加载时显示在页面上)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据绑定</title>
<script src="angular.js"></script>
</head>
<body>
<!-- ng-app指定angular作用域 ng-init初始化数据值 -->
<div ng-app="" ng-init="name='ion';pwd=123456;istrue=true">
<input type="text" ng-model="name">
<!-- 注意ng-bind会拿name覆盖掉标签内的所有内容 -->
<div ng-bind="istrue?name:''">我叫:xxx</div>
<div>我叫:{{name}}</div>
</div>
</body>
</html>
<!-- 可以通过控制台-->
2、数据循环
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据循环</title>
<script src="angular.js"></script>
</head>
<body>
<div ng-app="" ng-init="items=[2,5,3,2];json={'a':1,'b':2,'c':3}">
<ul>
<!-- track by 指定唯一key。
angular出于性能考虑需要数据和视图有一一对应的关系,这里数组出现重复数据不指定唯一key会报错 -->
<!-- 使用track by 也会导致删除数组一个元素后$index全部发生了改变,视图又要重新渲染 -->
<li ng-repeat="(index,item) in items track by $index">{{index}}-{{item}}</li>
</ul>
<!-- 另一点值得注意的就是当item是数组或者对象时即使内容相同也不需要指定唯一key,因为数组或对象的即使内容相同,当时其都是new Array或者new Object出来的新对象,并不相等,如下代码测试: -->
<button onclick="check0()">button0</button>
<button onclick="check1()">button1</button>
<button onclick="check2()">button2</button>
<button onclick="check3()">button3</button>
<ul>
<!-- 这里不能用$Index,因为这个是下标顺序 -->
<li ng-repeat="(key,value) in json">{{key}}-{{value}}</li>
</ul>
</div>
<script>
function check0(){
alert("1==1:"+(1==1)); //true
}
function check1(){
alert("'a'=='a':"+('a'=='a')); //true
}
function check2(){
alert("[1,2,3]==[1,2,3]:"+([1,2,3]==[1,2,3])); //false
}
function check3(){
alert('{"name":"ion","age":22}=={"name":"ion","age":22}:'+({"name":"ion","age":22}=={"name":"ion","age":22})); //false
}
</script>
</body>
</html>
3、ng环境与js环境
(1)ng环境与js环境不互通
<!DOCTYPE html>
<html lang="en" ng-app="">
<head>
<meta charset="UTF-8">
<title>ng环境与js环境不互通</title>
<script src="angular.js"></script>
</head>
<body ng-init="a=2">
<input type="text" ng-model="a">
<input type="button" value="输出" onclick="showmsg()">
<script>
function showmsg() {
console.log(a); //Uncaught ReferenceError: a is not defined
}
</script>
</body>
</html>
(2)ng事件(用法和js相似)
- ng-click
- ng-dbl-click
- ng-mousedown
- ng-mouseenter
- ng-mouseleave
- ng-mousemove
- ng-keydown
- ng-keyup
- ng-keypress
- ng-change
<!DOCTYPE html>
<html lang="en" ng-app="">
<head>
<meta charset="UTF-8">
<title>ng事件</title>
<script src="angular.js"></script>
</head>
<body ng-init="arr=[{name:'ion'}]">
<input type="text" ng-model="name">
//ng事件能操作ng环境的变量
<input type="button" value="输出" ng-click="arr.unshift({name:name})">
<ul>
<li ng-repeat="json in arr">What you input is: {{json.name}}</li>
</ul>
</body>
</html>
(3) 模块与controller $scope作用域(打通ng环境与js环境)
<!DOCTYPE html>
<!-- 1.2用模块:将模块名写在ng-app上 -->
<html lang="en" ng-app="test">
<head>
<meta charset="UTF-8">
<title>angular模块</title>
<script src="angular.js"></script>
<script>
//1.1声明模块:module的第一个参数是模块名称,第二个参数是该模块依赖于哪些模块,是个数组
let mod = angular.module('test',[]);
//2.1写controller,一个模块中可以有多个controller
mod.controller('ctrl1',function($scope){
// 这里是ng环境配置方法,方法里面的parseInt是js环境下的函数
$scope.parseInt = function (str){
return parseInt(str);
}
});
</script>
</head>
<!-- 2.2用controller -->
<body ng-controller="ctrl1">
<input type="text" ng-model="a">
<input type="text" ng-model="b">
<!-- 注意parseInt是js环境的函数,angular要调用要加到$scope域下 -->
{{parseInt(a)+parseInt(b)}}
</body>
</html>
4、内置过滤器和自定义过滤器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>系统过滤器</title>
</head>
<style>
div[ng-app] div{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
div[ng-app] div:nth-child(odd){background-color: #795548;}
}
</style>
<body>
<div ng-app="myApp" ng-controller="myController">
<div>
单价:<input type="number" ng-model="price" /> <br/>
数量:<input type="number" ng-model="quantity" /> <br/>
总价:{{(price*quantity) | currency}}
</div>
<div>
筛选数据显示<br/>
<input type="text" ng-model="search" placeholder="输入筛选条件" />
<ul>
<!-- 注意使用时需要加上冒号和筛选值 orderBy也是如此,相当于过滤器参数用冒号添加-->
<li ng-repeat="item in items | filter:search">
{{item}}
</li>
</ul>
</div>
<div>
自定义过滤器stringMerge<br/>
<!-- 传参就往后面加“:[参数]”,但是注意第一个参数在管道符|前面 -->
字符拼接:<em>{{ msg | stringMerge:'are':'god' }}</em>
</div>
</div>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp', []);
app.controller('myController', ['$scope','$filter',function($scope,$filter) {
$scope.price = 9.99;
$scope.quantity = 2;
$scope.items=['大黑','小红','大白','小兰'];
//在JavaScript代码中可以通过$filter来调用过滤器
$scope.msg=$filter('lowercase')('ION');
}]);
app.filter('stringMerge', function() { //可以注入依赖
return function(text,text1,text2) {
return text+" "+text1+" "+text2;
}
});
</script>
</body>
</html>
自定义过滤器判断字符是否被包含:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="angular.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="myController">
<div ng-if="surname | isInclude:name">{{'ion' | isInclude:name}}</div>
</div>
</body>
<script>
//将控制器写成【name】-Controller 而不是 【name】-Ctrl是一种最佳实践
angular.module('myApp',[]).controller('myController',function ($scope) {
$scope.name = 'ion luo';
$scope.surname = 'luo';
}).filter('isInclude',function () {
return function (txt1,txt2) {
if(txt2.indexOf(txt1)>-1){
return true;
}
else{
return false;
}
}
});
</script>
</html>
5、内置服务和自定义服务
常见的angular内置服务有:$location、$http、$timeout()和$interval()
可以认为服务就是在angular应用的的一些函数(后两个)或者对象(前两个)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>内置服务</title>
<style>
*{margin:0;padding: 0;}
body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
body p:nth-child(odd){background-color: #795548;}
</style>
</head>
<body ng-app="myApp" ng-controller="myController">
<p>
$location服务用于返回当前页面的URL地址:<br/>
{{myUrl}}
</p>
<p>
$http 是 AngularJS 应用中最常用的服务。服务向服务器发送请求,应用响应服务器传送过来的数据。<br/>
服务器返回:{{myDate}}
</p>
<p>
$timeout 服务对应了 JS window.setTimeout 函数。<br/>
$interval 服务对应了 JS window.setInterval 函数。<br/>
在angular应用中最好使用angular的服务而不是js的相似功能函数,因为angular服务的支持性更好
用法一样,我们举一个$timeout服务例子,5s后显示"欢迎您"。
</p>
</body>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp',[]);
app.controller('myController',['$scope','$location','$http','$timeout',function($scope,$location,$http,$timeout){
// $location服务用于返回当前页面的URL地址
$scope.myUrl = $location.absUrl();
// $http 是 AngularJS 应用中最常用的服务。服务向服务器发送请求,应用响应服务器传送过来的数据。
$http.get('welcome.php').then(function(response){
$scope.myDate = response.date;
},function(){
$scope.myDate = "返回数据失败!";
});
// $timeout 服务对应了 JS window.setTimeout 函数。
//$interval 服务对应了 JS window.setInterval 函数。
$timeout(function(){
alert("欢迎您!");
},5000);
}]);
</script>
</html>
自定义对象服务
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定义服务</title>
<style>
*{margin:0;padding: 0;}
body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
</style>
</head>
<body ng-app="myApp" ng-controller="myController">
<p>
自定义服务:用于将十进制数字转化成十六进制<br/>
<!-- 注意这里更改input的值不会更新hex的值 -->
<input type="number" ng-model="decimalism"><br/>
{{ decimalism }}的十六进制为:{{ hex }}
</p>
</body>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp',[]);
//自定义对象服务
app.service('hexafy',function(){
this.myFun = function(param){
return param.toString(16);
}
});
app.controller('myController',function($scope,hexafy){
$scope.decimalism = 50;
$scope.hex = hexafy.myFun($scope.decimalism);
});
</script>
</html>
6、$http服务
get和post请求的简写格式:
$http.get('/someUrl', config).then(successCallback, errorCallback);
$http.post('/someUrl', data, config).then(successCallback, errorCallback);
7、依赖注入
AngularJS 提供很好的依赖注入机制。以下5个核心组件用来作为依赖注入:
- (1)value
Value 是一个简单的 javascript 对象,用于向控制器传递值(配置阶段):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>依赖注入</title>
<style>
*{margin:0;padding: 0;}
body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
</style>
</head>
<body ng-app="myApp" ng-controller="myController">
<p>
{{ number }}
</p>
</body>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp',[]);
//// 创建 value 对象 "defaultValue" 并传递数据
app.value('defaultValue',5);
//将 defaultValue 注入控制器
app.controller('myController',function($scope,defaultValue){
$scope.number = defaultValue;
});
</script>
</html>
- (2)service
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>依赖注入</title>
<style>
*{margin:0;padding: 0;}
body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
</style>
</head>
<body ng-app="myApp" ng-controller="myController">
<p>
{{ number }}
</p>
</body>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp',[]);
//定义服务'calcService',该服务中有个方法square返回一个数字的平方
app.service('calcService',function(){
this.square = function(a){
return a*a;
}
});
//将服务注入控制器
app.controller('myController',function($scope,calcService){
$scope.number = calcService.square(5);
});
</script>
</html>
- (3)factory
factory 是一个函数用于返回值。在 service 和 controller 需要时创建。也就是说可以引入到service或者controller。通常我们使用 factory 函数来计算或返回值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>依赖注入</title>
<style>
*{margin:0;padding: 0;}
body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
</style>
</head>
<body ng-app="myApp" ng-controller="myController">
<p>
{{ number }}
</p>
</body>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp',[]);
//创建一个 factory 'MathService'用于计算两个数字的乘积
app.factory('MathService',function(){
var factory = {};
factory.multiply = function(a,b){
return a*b;
}
return factory;
});
//在service中注入factory,当然controller注入也可以
app.service('calcService',function(MathService){
this.multi = function(a,b){
return MathService.multiply(a,b);
}
});
//再将服务注入控制器
app.controller('myController',function($scope,calcService){
$scope.number = calcService.multi(5,6);
});
</script>
</html>
- (4)constant
constant(常量)用来在配置阶段传递数值,注意这个常量在配置阶段是不可用的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>依赖注入</title>
<style>
*{margin:0;padding: 0;}
body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
</style>
</head>
<body ng-app="myApp" ng-controller="myController">
<p>
{{ number }}
</p>
</body>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp',[]);
//声明一个常量
app.constant('constValue','5');
//将常量注入控制器
app.controller('myController',function($scope,constValue){
$scope.number = constValue;
});
</script>
</html>
- (5)provider
AngularJS 中通过 provider 创建一个 service、factory等(配置阶段)。Provider 中提供了一个 factory 方法 get(),它用于返回 value/service/factory。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>依赖注入</title>
<style>
*{margin:0;padding: 0;}
body p{background-color: #e91e63;line-height: 2.0;padding: 15px 30px;color: #fff;}
</style>
</head>
<body ng-app="myApp" ng-controller="myController">
<p>
{{ number }}
</p>
</body>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp',[]);
// 配置service/factory
app.config(function($provide) {
$provide.provider('MathService', function() {
this.$get = function() {
var factory = {};
factory.multiply = function(a, b) {
return a * b;
}
return factory;
};
});
});
//将MathService注入控制器
app.controller('myController',function($scope,MathService){
$scope.number = MathService.multiply(5,6);
});
</script>
</html>
8、路由
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>AngularJS 路由实例 - 菜鸟教程</title>
<script src="angular.js"></script>
<script src="https://cdn.bootcss.com/angular.js/1.7.0/angular-route.min.js"></script>
</head>
<body ng-app='routingDemoApp'>
<h2>AngularJS 路由应用</h2>
<ul>
<li><a href="#!/">首页</a></li>
<li><a href="#!/computers">电脑</a></li>
<li><a href="#!/printers">打印机</a></li>
<li><a href="#!/blabla">其他</a></li>
</ul>
<div ng-view></div>
<script>
angular.module('routingDemoApp',['ngRoute'])
.config(function($routeProvider){
$routeProvider
.when('/',{template:'这是首页页面'})
.when('/computers',{template:'这是电脑分类页面'})
.when('/printers',{template:'这是打印机页面'})
.otherwise({redirectTo:'/'});
});
</script>
</body>
</html>
路由配置时设置对象:
AngularJS 路由也可以通过不同的模板来实现。
$routeProvider.when 函数的第一个参数是 URL 或者 URL 正则规则,第二个参数为路由配置对象。
路由配置对象语法规则如下:
$routeProvider.when(url, {
template: string,
templateUrl: string,
controller: string, function 或 array,
controllerAs: string,
redirectTo: string, function,
resolve: object<key, function>
});
参数说明:
-
template:
如果我们只需要在 ng-view 中插入简单的 HTML 内容,则使用该参数:
.when('/computers',{template:'这是电脑分类页面'})
-
templateUrl:
如果我们只需要在 ng-view 中插入 HTML 模板文件,则使用该参数:
$routeProvider.when('/computers', { templateUrl: 'views/computers.html', });
以上代码会从服务端获取 views/computers.html 文件内容插入到 ng-view 中。
-
controller:
function、string或数组类型,在当前模板上执行的controller函数,生成新的scope。
-
controllerAs:
string类型,为controller指定别名。
-
redirectTo:
重定向的地址。
-
resolve:
指定当前controller所依赖的其他模块。
9、组件通信
(1)通过公共服务
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body ng-app="myApp">
<directive1></directive1>
<directive2></directive2>
</body>
<script src="angular.js"></script>
<script>
var app = angular.module('myApp',[]);
//公共对象服务
app.service('shareService',function () {
this.names = [];
this.addName = function(name){
this.names.push(name);
}
});
//元素指令1,通过公共服务添加输入值到公共服务names数组
app.directive('directive1',function(shareService){
return {
restrict:"E",
template:"name: <input type='text' ng-model='new_name'/><br/><button ng-click='addName()'>Add</button>",
link:function (scope,element,attrs) {
scope.addName = function () {
if(scope.new_name){
shareService.addName(scope.new_name);
}
}
}
}
});
//元素指令2,通过公共服务读取通过服务里面的names值
app.directive('directive2',function (shareService) {
return {
restrict:"E",
template:"<ul><li ng-repeat='list in lists'>{{list}}</li></ul>",
link:function (scope,element,attrs) {
scope.lists = shareService.names;
}
}
});
</script>
</html>
(2)通过link的attrs实现同一个dom下组件通信
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body ng-app="myApp">
<directive1 directive2></directive1>
</body>
<script src="angular.js"></script>
<script>
<!--
每个directive在定义的时候都有一个link函数,函数签名的第三个参数是attrs,代表在该directive上面的
所有atrributes数组,attrs提供了一些方法,比较有用的是$set和$observe,前者可以自定义attr或修改已经有
的attr的值,后者可以监听到该值的变化。利用这种方式,我们可以让在位于同一个dom元素上的两个directive进
行通讯,因为它们之间共享一个attrs数组。
-->
var app = angular.module('myApp',[]);
app.directive('directive1',function(){
return {
restrict:"E",
template:"<span>{{ time | date:'yyyy-MM-dd HH:mm:ss'}}</span>",
link:function (scope,element,attrs) {
attrs.$observe('showValue',function (newValue) {
scope.time = newValue;
});
}
}
});
app.directive('directive2',function ($interval) {
return {
restrict:"A",
link:function (scope,element,attrs) {
let defInterval = $interval(function () {
attrs.$set("showValue",new Date().getTime());
},1000);
scope.$on('$destory',function(){
$interval.cancel(defInterval);
});
}
}
});
</script>
</html>
10、系统指令
全部angular系统指令可见angular参考手册,http://www.runoob.com/angularjs/angularjs-reference.html。下面介绍些常用系统指令:
(1)ng-class 和 ng-style
<!DOCTYPE html>
<html ng-app="">
<head>
<meta charset="utf-8">
<title>常见系统指令</title>
<script src="angular.js"></script>
<style>
.container{width:100px;height:100px;background-color:yellow}
.box{display: inline-block; }
</style>
</head>
<!-- 注意ng-style里面的属性两个单词需要连写并且后首字母大写 -->
<body ng-init="a='width:100px;height:100px;background-color:red';
b={width:'100px',height:'100px',backgroundColor:'blue'};
c='container box';
d=['container','box']">
<div style="{{ a }}"></div>
<div ng-style="b"></div>
<div class="{{ c }}"></div>
<div ng-class="d"></div>
</body>
</html>
效果:
(2)ng-switch
该指令和 ng-if 一样当满足条件才渲染到HTML中。(注意 ng-if 没有 ng-else 指令来做if-else条件结构,需要时使用ng-switch)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>常见系统指令</title>
<script src="angular.js"></script>
</head>
<body ng-app="">
<select ng-model="site">
<option value="taobao">淘宝</option>
<option value="zhihu">知乎</option>
<option value="jingdong">京东</option>
</select>
<div ng-switch="site">
<div ng-switch-when="taobao"><h1>淘宝</h1></div>
<div ng-switch-when="zhihu"><h1>知乎</h1></div>
<div ng-switch-when="jingdong"><h1>京东</h1></div>
<div ng-switch-default><h1>请选择 >>>>>></h1> </div>
</div>
</body>
</html>
(3) ng-bind-html 和 $sce.trustAsHtml()
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<title>ng-bind-html和$sce</title>
<script src="angular.js"></script>
</head>
<body ng-controller= "myController">
<div ng-bind-html="a"></div>
</body>
<script>
var app = angular.module('myApp',[]);
app.controller('myController',function($scope,$sce){
$scope.a = $sce.trustAsHtml("欢迎来到<a href='https://blog.csdn.net/ion_L' target='_blank'>ion的博客</a>");
});
</script>
</html>
注意,低版本的angluar可以直接绑定HTML代码,但是在anglar1.6.4之后必须加上$sce才可以,否则会出现如下报错。
关于$sce的具体内容见:https://www.cnblogs.com/xing901022/p/5100551.html