本系列博客采用的Angularjs1.3进行开发
要入门Angularjs主要掌握以下概念
1.数据绑定(MVC)
2.scope
3.模块(module)
4.Directive
5.路由
6.依赖注入
数据绑定
首先是HelloWorld的教程
<!doctype html>
<!-- ng-app声明以下部分使用angularjs -->
<html ng-app>
<head>
<meta charset="utf-8">
</head>
<body>
<!-- 定义model -->
<input type="text" name="msg" ng-model="name">
<!-- 绑定model内容 -->
<span ng-bind='name'></span>
<!-- 因为加载js需要时间,下面这种方式可能会显示出花括号 -->
<!-- <span >{{name}}</span> -->
</body>
<script src="js/angular-1.3.0.js"></script>
</html>
当我们改变input的内容时,model的值也会改变
下面介绍一下数据绑定如何运用在mvc设计模式中
<!doctype html>
<html ng-app>
<head>
<meta charset="utf-8">
</head>
<body>
<!-- 使用Controller作为中介 -->
<div ng-controller="HelloAngular">
<p><span ng-bind="greeting.text"></span>,Angular</p>
</div>
</body>
<script src="js/angular-1.3.0.js"></script>
<script >
// 定义Controller,名字要和所绑定的ng-controller一样
function HelloAngular($scope) {
// scope代表作用域,每个controller都有自己的scope,接下来会详细介绍
$scope.greeting = {
text: 'Hello'
};
}
</script>
</html>
scope
scope是一个POJO,可以叫做作用域,可以继承父作用域的属性和方法,就是说当controller嵌套时,可以使用父controller里的scope的属性和方法
ng-app定义了一个angular模块, 每个模块只有一个$rootScope,只有一个$injector,但可以有多个$scope 。scope有点类似React的store,还有scope中也可以存放方法。
<!doctype html>
<html ng-app>
<head>
<meta charset="utf-8">
</head>
<body>
<div >
<!-- 分别绑定不同的Controller -->
<div ng-controller="GreetCtrl">
<!-- 这个name属于GreetCtrl的scope -->
Hello {{name}}!
</div>
<div ng-controller="ListCtrl">
<ol>
<li ng-repeat="name in names">
<!-- name是names中的迭代的对象 ,names属于ListCtrl的scope-->
<!-- department是rootscope的model,可以共用 -->
{{name}} from {{department}}
</li>
</ol>
</div>
</div>
</body>
<script src="js/angular-1.3.0.js"></script>
<script >
function GreetCtrl($scope, $rootScope) {
$scope.name = 'World';
// rootscope可以共用
$rootScope.department = 'Angular';
}
function ListCtrl($scope) {
$scope.names = ['Igor', 'Misko', 'Vojta'];
}
</script>
</html>
模块化
通常我们为了避免全局变量污染,我们会引入module这个概念,有点类似命名空间
我们把上面MVC的例子改成模块化
<!doctype html>
<html ng-app="HelloAngular">
<head>
<meta charset="utf-8">
</head>
<body>
<div ng-controller="helloAngular">
<p>{{greeting.text}},Angular</p>
</div>
</body>
<script src="js/angular-1.3.0.js"></script>
<script type="text/javascript">
// 首先为ng-app定义一个module,[]中填写依赖项
var myModule = angular.module("HelloAngular", []);
// 定义module所需的controller,引入scope
myModule.controller("helloAngular", ['$scope',
function HelloAngular($scope) {
$scope.greeting = {
text: 'Hello'
};
}
]);
</script>
</html>
Directive
我们可以使用Directive来匹配不同的dom,来显示不同模板,也可以用过这种方式实现view的复用
主要有四种匹配模式
A——匹配属性中含有指定值
C——class中含有指定值
M——一般标签,标签上有注释directive:指定值
E——匹配标签为指定值
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
</head>
<body>
<!-- 自定义hello标签 -->
<!-- 匹配模式为E -->
<hello></hello>
<!-- 匹配模式为A -->
<div hello></div>
<!-- 匹配模式为C -->
<div class="hello"></div>
<!-- 匹配模式为M -->
<!-- directive:hello -->
<div></div>
</body>
<script src="js/angular-1.3.0.js"></script>
<script >
// 模块化
var myModule = angular.module("MyModule", []);
// 匹配hello
myModule.directive("hello", function() {
return {
restrict: 'AEMC',//使用4种匹配模式
template: '<div>Hi everyone!</div>',
replace: true//完全代替标签里的内容
//transculde表示互相嵌套
// transclude:true,
//<div ng-transclude></div>为原标签里的内容
// template: '<div>Hi everyone!<div ng-transclude></div></div>',
}
});
</script>
</html>
Directive除了可以代替指定标签的内容,还可以实现方法或者属性的操作
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
</head>
<body>
<div ng-controller="MyCtrl1">
<!-- 属性放不同的方法名 -->
<loader howToLoad="loadData1()">LoadData1</loader>
</div>
<div ng-controller="MyCtrl2">
<loader howToLoad="loadData2()">LoadData2</loader>
</div>
<script src="js/angular-1.3.0.js"></script>
<script >
// 模块化
var myModule = angular.module("MyModule", []);
myModule.controller('MyCtrl1',['$scope',function($scope){
$scope.loadData1=function(){
console.log("loading1");
}
}]);
myModule.controller("MyCtrl2",['$scope',function($scope){
$scope.loadData2=function(){
console.log("loading2");
}
}]);
// 匹配superman
myModule.directive("loader", function() {
return {
restrict:"AE",
// 三个参数分别是作用域,dom对象,属性
link:function(scope,elemenet,attrs){
//绑定标签方法,鼠标在标签上方时触发
elemenet.bind('mouseenter',function(){
// 下面都两种可以执行controller里的方法,若没有方法则报错
// scope.loadData1();
// scope.$apply("loadData1()");
//执行相应属性的方法,属性名要全部小写
scope.$apply(attrs.howtoload);
});
}
}
});
</script>
</body>
</html>
以下例子实现指令的依赖(继承)
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
</head>
<body>
<div class="row">
<div class="col-md-3">
<superman strength>动感超人——力量</superman>
</div>
</div>
<div class="row">
<div class="col-md-3">
<superman strength speed>动感超人——力量+敏捷</superman>
</div>
</div>
<div class="row">
<div class="col-md-3">
<superman strength speed light>动感超人——力量+敏捷+发光</superman>
</div>
</div>
<link rel="stylesheet" type="text/css" href="css/bootstrap-3.0.0/css/bootstrap.css">
<script src="js/angular-1.3.0.js"></script>
<script >
// 模块化
var myModule = angular.module("MyModule", []);
// 匹配superman
myModule.directive("superman", function() {
return {
scope:{},
//使用A和E模式
restrict:'AE',
//暴露方法给指令调用
controller:function($scope){
$scope.abilities=[];
this.addStrength=function(){
$scope.abilities.push("strength");
};
this.addSpeed=function(){
$scope.abilities.push("speed");
};
this.addLight=function(){
$scope.abilities.push("light");
};
},
link:function(scope,elemenet,attrs){
//修改元素class
elemenet.addClass('btn btn-primary');
//绑定标签方法,鼠标在标签上方时触发
elemenet.bind('mouseenter',function(){
console.log(scope.abilities);
});
}
}
});
myModule.directive('strength',function(){
return {
//依赖superman指令
require:'^superman',
//supermanCtrl是superman指令里的controller,需要把它注入到link中
link:function(scope,elemenet,attrs,supermanCtrl){
supermanCtrl.addStrength();
}
}
});
myModule.directive('speed',function(){
return {
require:'^superman',
link:function(scope,elemenet,attrs,supermanCtrl){
supermanCtrl.addSpeed();
}
}
});
myModule.directive('light',function(){
return {
require:'^superman',
link:function(scope,elemenet,attrs,supermanCtrl){
supermanCtrl.addLight();
}
}
});
</script>
</body>
</html>
如果想每一处都使用独立的scope,则要加上scope:{},不加则默认使用同一个scope,互相影响
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
</head>
<body>
<hello></hello>
<hello></hello>
<hello></hello>
<hello></hello>
<script src="js/angular-1.3.0.js"></script>
<script >
// 模块化
var myModule = angular.module("MyModule", []);
// 匹配superman
myModule.directive("hello", function() {
return {
scope:{},//使用独立的scope,每一处匹配的标签的scope都是独立的,不互相影响
restrict:"AE",
template:'<div><input type="text" ng-model="userName"/>{{userName}}</div>'
}
});
</script>
</body>
</html>
scope的绑定有三种方式:@,=,&
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
</head>
<body>
<div ng-controller="MyCtrl">
Ctrl:
<input type="text" ng-model="ctrlFlavor">
<br>
Directive:
<drink flavor="ctrlFlavor"></drink>
</div>
<script src="js/angular-1.3.0.js"></script>
<script >
// 模块化
var myModule = angular.module("MyModule", []);
myModule.controller('MyCtrl',['$scope',function($scope){
$scope.ctrlFlavor="百威";
}])
// 匹配drink
myModule.directive("drink", function() {
return {
restrict:"AE",
template:'<input type="text" ng-model="flavor"/>{{flavor}}',
scope:{
flavor:'='//双向绑定model,绑定该属性值的model,改变任一个model都会互相影响
}
// scope:{
// flavor:'@'//将原来该名字属性的字符串传递下来 ,和下面表达相等
// }
// link:function(scope,element,attrs){
// scope.flavor=attrs.flavor;
// }
}
});
</script>
</body>
</html>
如果要传递方法则要使用&
<!doctype html>
<html ng-app="MyModule">
<head>
<meta charset="utf-8">
</head>
<body>
<div ng-controller="MyCtrl">
<greeting greet="sayHello(name)"></greeting>
<greeting greet="sayHello(name)"></greeting>
<greeting greet="sayHello(name)"></greeting>
</div>
<script src="js/angular-1.3.0.js"></script>
<script >
// 模块化
var myModule = angular.module("MyModule", []);
myModule.controller('MyCtrl',['$scope',function($scope){
$scope.sayHello=function(name){
alert("hello"+name);
}
}])
// 匹配superman
myModule.directive("greeting", function() {
return {
restrict:"AE",
template:'<input type="text" ng-model="userName"/><br/><button ng-click="greet({name:userName})"> greeting</button><br>',
scope:{
greet:'&'//将原来该名字属性的方法传递下来
}
}
});
</script>
</body>
</html>
路由
<html>
<head>
<meta charset="utf-8">
</head>
<body ng-app='routingDemoApp'>
<h2>AngularJS 路由应用</h2>
<ul>
<!-- 设置不同url -->
<li><a href="#/">首页</a></li>
<li><a href="#/computers">电脑</a></li>
<li><a href="#/printers">打印机</a></li>
<li><a href="#/blabla">其他</a></li>
</ul>
<!-- 内容将替换ng-view的标签 -->
<div ng-view></div>
<script src="js/angular-1.3.0.js"></script>
<script src="http://apps.bdimg.com/libs/angular-route/1.3.13/angular-route.js"></script>
<script>
// 依赖ngRoute
angular.module('routingDemoApp',['ngRoute'])
//要注入$routeProvider
.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/',{template:'这是首页页面'})
.when('/computers',{template:'这是电脑分类页面'})
.when('/printers',{template:'这是打印机页面'})
.otherwise({redirectTo:'/'});
}]);
</script>
</body>
</html>
依赖注入
用过spring的人都知道什么是依赖注入,依赖注入就是弄一个中央的容器,当你需要你就注入
AngularJS 提供很好的依赖注入机制。以下5个核心组件用来作为依赖注入:
1. value
2. factory
3. service
4. provider
5. constant
下面用一个简单的乘方例子来演示
<html>
<head>
<meta charset="utf-8">
<title>AngularJS 依赖注入</title>
</head>
<body>
<h2>AngularJS 简单应用</h2>
<div ng-app = "mainApp" ng-controller = "CalcController">
<p>输入一个数字: <input type = "number" ng-model = "number" /></p>
<button ng-click = "square()">X<sup>2</sup></button>
<p>结果: {{result}}</p>
</div>
<script src="js/angular-1.3.0.js"></script>
<script>
var mainApp = angular.module("mainApp", []);
// 使用provider的方法创建service factory
mainApp.config(function($provide) {
$provide.provider('MathService', function() {
this.$get = function() {
var factory = {};
factory.multiply = function(a, b) {
return a * b;
}
return factory;
};
});
});
// 使用factory的方法创建service factory
// mainApp.factory('MathService', function() {
// var factory = {};
// factory.multiply = function(a, b) {
// return a * b;
// }
// return factory;
// });
// 在 service 中注入 factory "MathService"
mainApp.service('CalcService', function(MathService){
this.square = function(a) {
return MathService.multiply(a,a);
}
});
//设置一个值
mainApp.value("defaultInput", 5);
// 在controller中注入$scope,CalcService和defaultInput,因为scope是angular里面的属性,所以要加上$
mainApp.controller('CalcController', function($scope, CalcService, defaultInput) {
$scope.number = defaultInput;
$scope.result = CalcService.square($scope.number);
$scope.square = function() {
//调用service的方法
$scope.result = CalcService.square($scope.number);
}
});
</script>
</body>
</html>
Angularjs是一个很优秀且前卫的js库,掌握了它,开发的效率会更加高效,业务逻辑也更加的清晰,而且它吸收了很多流行后端框架的思想,所以后端人员学习起来成本也是相当的低,Angularjs是全栈工程师一个不错的选择