angular学习笔记(2)
这里接着上一篇继续写笔记,废话不多说,直接进入正题……
angular的服务
上篇文章说到,不要去试图复用controller。但是如果两个controller中有相同的功能该怎么办?
这个时候服务就起到作用了。angular内置有很多服务给我们使用,当然也可以给我们自定义服务。
$http服务
$http服务是angular中使用得最频繁的服务,因为前台要不断和后台交互,所以$http使用得最频繁的一个服务。
HTML:
<div ng-controller="myController">
<ul>
<li ng-repeat="data in datas">{{data.data}}</li>
</ul>
</div>
JS:
myApp.controller("myController",["$scope","$http",function($scope,$http){
$http({
method:"GET",
url:"dataUrl"
}).success(function(data,status){
$scope.datas=data;
}).error(function(data,status){
consloe.log("error")
});
}]);
模拟的数据:
[
{
"data":"1"
},
{
"data":"2"
},
{
"data":"3"
}
]
这样就会在页面输出:
·1
·2
·3
这个和jquery的$.ajax方法很相似,这个是$http的API,嘿嘿~。
$filter服务
$filte也是angular中比较常用的服务,angular内置了9个filter分别是:currency(货币),date(日期),json(将数据转化为json),lowercase(小写),number(数字),orderBy(排序),uppercase(大写),limitTo(限定字符串或者数组长度)。
filter可以嵌套使用(使用管道符号|分隔)。
<p>{{time| date:"y-M-d H-m-s"}}</p>
例如上面这个会在页面输出年、月、日、时、分、秒。
自定义过滤器
这里用上面的http的例子:
HTML改为:
<div ng-controller="myController">
<ul>
<li ng-repeat="data in datas | myFilter">{{data.data}}</li>
</ul>
</div>
JS中添加:
myApp.filter("myFilter", function () {
return function (obj) {
var newObj = [];
angular.forEach(obj, function (obj) {
if (obj.data.indexOf("1") !== -1) {
newObj.push(obj);
}
});
return newObj;
}
});
上面代码执行完以后会在页面打印出:
·1
当然,还有一种方法是在$scope上定义一个方法用作过滤器:
HTML:
<div ng-controller="myController">
<ul>
<li ng-repeat="data in datas | filter: myFilter">{{data.data}}</li>
</ul>
</div>
JS:
myApp.filter("myFilter", function () {
return function (obj) {
var newObj = [];
angular.forEach(obj, function (obj) {
if (obj.data.indexOf("1") !== -1) {
newObj.push(obj);
}
});
return newObj;
}
$scope.myFilter=function(obj){
if (obj.data.indexOf("1") !== -1) {
return true;
}
return false;
}
});
这样也可以得到同样的结果。
当然,还有其他方法,在这我就不一一列举了。
自定义服务
在angular中有三种方法自定义服务,分别是$provide.provider,factory,server,这些方法的本质都是provider,只不过是后面两种方法将$provide.provider封装了一下,让我们使用起来更方便。
HTML:
<div ng-controller="myController"></div>
JS:
var myApp = angular.module("myApp", [], ["$provide",function ($provide) {
$provide.provider("myServer", function () {
this.$get = function () {
return function () {
console.log("myServer");
}
}
});
$provide.factory("myServer2",function(){
return function(){
console.log("myServer2");
}
});
$provide.service("myServer3",function(){
return function(){
console.log("myServer3");
}
});
}]);
myApp.controller("myController",["$scope","myServer","myServer2","myServer3",function($scope,myServer,myServer2,myServer3){
myServer();
myServer2();
myServer3();
}]);
在上面,用三种方法创建了三个服务,运行以后在控制台会输出myServer、myServer2、myServer3。下面两个方法虽然写法一样,但是还是有些不同的,factory能返回所有数据类型的数据,而service只能返回对象或者应用类型的数据,例如:service不能直接返回字符串。
后面两种快捷方法可以不用写在回调函数里面,可以写成:
myApp.factory("serverName",function(){
return ...
});
myApp.service("serverName",function(){
return ...
});
路由
angular提供了一个路由的功能用于改变视图。只要链接改变,就可以改变相应的视图。如果需要使用得通过npm把angular-router从网上下下来。
使用的时候需要先注册:
var myApp = angular.module("myApp", ['ngRoute']);
完以后就可以使用了,首先,主html文件里面加上:
<div ng-view></div>
1.html文件上(文件名可以随意取,文件内容也可以自己定):
<ul>
<li ng-repeat="t in texts"></li>
</ul>
2.html:
<h1>我是标题</h1>
<p ng-bind="text"></p>
JS:
myApp.controller("helloCtrl",["$scope",function($scope){
$scope.texts=["hello world","hello angular"];
}]);
myApp.controller("textCtrl",["$scope",function($scope){
$scope.text="我是内容";
}]);
/*路由的配置*/
myApp.config(function($routeProvider){
$routerProvider.when("/hello",{
templateUrl:"1.html",
controller:"helloCtrl"
}).when("/text",{
templateUrl:"2.html",
controller:"textCtrl"
}).otherwise({
redirectTo:"/hello"
})
});
从上面的js文件的配置可以看出,当地址栏输入/hello结尾的当前服务器地址时会将1.html里的内容放到主html文件的<div ng-view></div>内,当输入/text时就是2.html,其他的都默认为以/hello结尾,下面的控制器是必不可少的,用于控制相应的视图。
如果细心观察,会发现地址栏上的/前面会有个#,这个是为了防止浏览器向后台发送请求。
angular自带的路由有个缺陷,就是不能进行深层的嵌套路由。深层的嵌套路由就是路由里面还有路由。
不过,有个第三方的angular插件填补了这个缺陷,那就是ui-router,这个插件也得用npm下载:npm i angular-ui-router
使用时,也需要像angular-router一样那样注册:
var myApp = angular.module("myApp", ['ui.router']);
主html改为:
<div ui-view></div>
1.html:
<h1>1 page</h1>
<p>1</p>
<div ui-view="home"></div>
home.html:
<hr>
<h1>home page</h1>
<a ui-sref="link">link</a>
link.html:
<h1>link page</h1>
JS:
myApp.config(function($stateProvider,$urlRouterProvider){
$urlRouterProvider.otherwise("/index");
$stateProvider.state("index",{
url:"/index",
views:{
"":{
templateUrl:"1.html"
},
"home@index":{
templateUrl:"home.html"
}
}
}).state("link",{
url:"/link",
views:{
"":{
templateUrl:"link.html"
}
}
});
});
从js的配置可以看出,打开页面默认是以/index结尾的视图。
打开页面可以看到1.html的内容(一个标题,一段文字),1.html里面又嵌套了一个home.html的视图(一条线,一个标题,一个链接),链接点开后会转到link.html的视图(一个标题)。
tip:home@index的home代表主页面嵌套视图里面的ui-view的值,a链接里的ui-sref的值代表state的第一个参数。