效劳 Service
效劳这个观点实在并不生疏,比方在Java语言中便有如许的观点,其作用就是对外供应某个特定的功用,如音讯效劳,菜单效劳等,是一个自力的模块。
angular的效劳是如许定义的:
Angular services are singletons objects or functions that carry out specific tasks common to web apps.
在Angular中,效劳的实质是一些和控制器绑缚在一起的一个单例对象或函数,对外供应特定的功用。经由过程这些对象供应了在运用的全部生命周期都存有数据的要领,当重载或革新页面时,数据不会被消灭,而且还与加载之前保持一致。即不管这个效劳被注入到任何处所,对象一直只要一个实例。
这与我们自身定义一个function然后在其他处所挪用差别,由于效劳被定义在一个模块中,所以其运用局限是能够被我们治理的。angular的防止全局变量污染认识异常强。
内置效劳
Angular供应了许多内置效劳,如$scope、$http、$window、$location等。
我们引见一下$location。(注重效劳是怎样注入控制器的,后边会有零丁模块引见angular的依靠注入)
猎取url的相干要领:
<div ng-controller="MyController">
<div>当前的地点是: {{url}}</div>
<button ng-click="onclick()">显现地点</button>
</div>
angular.module('MyApp').controller('MyController'['$scope','$location',function($scope,$location){
$scope.onclick = function () {
$scope.url = $location.absUrl();
}
}])
以’http://39.106.222.235:8080/cds/personalCenter/index.html#/demandManager/view.html?orderId=10&projectId=42&mWin=false’ 这个途径为例:
1.猎取当前完全的url途径:
$location.absUrl():
http://39.106.222.235:8080/cds/personalCenter/index.html#/demandManager/view.html?orderId=10&projectId=42&mWin=false
*2.猎取当前url途径(当前url#背面的内容,包含参数和哈希值–哈希值引见):
$location.url();
// /demandManager/view.html?orderId=10&projectId=42&mWin=false
*3.猎取当前url的子途径(也就是当前url#背面的内容,不包含参数):
$location.path()
// /demandManager/view.html
4.猎取当前url的协定(比方http,https)
$location.protocol()
// http
5.猎取当前url的主机名
$location.host()
// localhost
6.猎取当前url的端口
$location.port()
// 80 (这里就是wamp的默许端口号)
*7.猎取当前url的哈希值(hash 属性是一个可读可写的字符串,该字符串是 URL 的锚部份)
$location.hash()
// null
*8.猎取当前url的参数的序列化json对象
$location.search()
// {‘orderId’:10,’projectId’:42,’mWin’:’false’}
修正url的相干要领:
于$location.search(),$location.url();,$location.path(),$location.hash(),这四种能够传入参数举行修正url,在这类状况下,函数的返回值都是$location自身:
1.修正url的子途径(也就是当前url#背面的内容,包含参数):
参数花样:字符串
$location.url('/demandCustomer/view.html?orderId=10&projectId=42&mWin=true');
//http://39.106.222.235:8080/cds/personalCenter/index.html#/demandCustomer/view.html?orderId=10&projectId=42&mWin=true
2.修正url的子途径部份(也就是当前url#背面的内容,不包含参数):
参数花样:字符串
$location.path('/demandCustomer/view.html');
//http://39.106.222.235:8080/cds/personalCenter/index.html#/demandCustomer/view.html?orderId=10&projectId=42&mWin=false
3.修正url的哈希值部份
参数花样:字符串
$location.hash('#footer');
//http://39.106.222.235:8080/cds/personalCenter/index.html#/demandManager/view.html?orderId=10&projectId=42&mWin=false#footer
4.修正url的参数部份(这是重点啊!!!!!!!!)
(1).传入两个参数,第一个参数的花样为字符串:
①第二个参数的花样也是字符串
第一个参数示意url参数的属性名,第二个参数是该属性名的属性值,假如是已有属性名,则修正,假如不是已有属性,则新增
$location.search('mWin','true')
//http://39.106.222.235:8080/cds/personalCenter/index.html#/demandManager/view.html?orderId=10&projectId=42&mWin=true
②第二个参数的花样为数组,数组中的各个值也是字符串或许布尔值
第一个参数示意url参数的属性名,第二个参数是该属性名的值,有多少个值,url中就会顺次反复涌现多少个.以下:
$location.search('projectSearch',['book','home'])
//http://39.106.222.235:8080/cds/personalCenter/index.html#/demandManager/view.html?orderId=10&projectId=42&mWin=false&projectSearch=book&projectSearch=home
(2).传入两个参数,第一个参数为字符串,第二个参数为null:
第一个值示意url参数的属性名,假如是已有属性名,则删除该属性,假如不是已有属性,那就即是没悛改
$location.search('projectId',null)
//http://39.106.222.235:8080/cds/personalCenter/index.html#/demandManager/view.html?orderId=10&mWin=false
(3).传入一个参数,花样为json对象:
直接用这个json对象里的键值对替换全部url的参数部份
①平常的键值对:
$location.search({orderId:11,projectId:45,mWin:true,projectSearch:'book'})
//http://39.106.222.235:8080/cds/personalCenter/index.html#/demandManager/view.html?orderId=11&projectId=45&mWin=true&projectSearch=book
②属性值为一个数组:
$location.search({orderId:11,projectId:45,mWin:true,projectSearch:['book','home']})
//http://39.106.222.235:8080/cds/personalCenter/index.html#/demandManager/view.html?orderId=11&projectId=45&mWin=true&projectSearch=book&projectSearch=home
(4).传入一个参数,花样为字符串:
直接用这个字符串替换全部url的参数部份(没有键值对,参数部份就是一个属性名)
$location.search('role')
//http://39.106.222.235:8080/cds/personalCenter/index.html#/demandManager/view.html?role
不存入历史纪录
在上文的一切修正url的要领的时刻,每修正一次,url都会被存入历史纪录,能够运用退却按钮回到修正前的url,假如不想要这类结果,而仅仅是替换当前的纪录,能够运用:
$location.replace();
例子:
// 原url:
// http://39.106.222.235:8080/cds/personalCenter/index.html#/demandManager/view.html?orderId=10&projectId=42&mWin=false
$location.url('/demandCustomer/view.html?orderId=10&projectId=45&mWin=true');
// 修正一次后:
// http://39.106.222.235:8080/cds/personalCenter/index.html#/demandCustomer/view.html?orderId=10&projectId=45&mWin=true
// 按下退却回到原url:
// http://39.106.222.235:8080/cds/personalCenter/index.html#/demandManager/view.html?orderId=10&projectId=42&mWin=false
// 再按下行进回到修正后url:
// http://39.106.222.235:8080/cds/personalCenter/index.html#/demandCustomer/view.html?orderId=10&projectId=45&mWin=true
$location.path('/demandCustomer').replace();
// 修正第二次后挪用replace():
// http://39.106.222.235:8080/cds/personalCenter/index.html#/demandCustomer/view.html?orderId=10&projectId=42&mWin=false
// 按下退却,不会回到第二次修正前的url,而是回到第一次修正前的url
// http://39.106.222.235:8080/cds/personalCenter/index.html#/demandManager/view.html?orderId=10&projectId=42&mWin=false
监听途径跳转
Angular也能够监听途径的变化,这些事宜我们会在路由中做解说。(待增加)
http要求
$http是Angular内置的效劳,用于效劳向效劳器发送要求,运用相应效劳器传送过来的数据。
写法:
写法一
$http({
method: 'GET', //能够改成POST
url: '/someUrl'
}).then(function successCallback(response) {
// 要求胜利实行代码
}, function errorCallback(response) {
// 要求失利实行代码
});
写法二
$http.get('/someUrl',config).then(successCallback, errorCallback);
$http.get('/someUrl',{params:{"id":3}}).then(successCallback, errorCallback);
$http.post('/someUrl', data:{name:"aaa",id:"1",age:"20"},config).then(successCallback, errorCallback);
jsonp写法
$http({
method: 'JSONP',
url: 'http://www.b.com/test.php?callback=JSON_CALLBACK'
}).success(function(response){
console.log(response);
});
$http.jsonp(
'http://www.b.com/test.php?callback=JSON_CALLBACK'
).success(function (response){
console.log(response);
});
//这里要注重,跨域要求的url后一定要追加参数callback,而且callback的值是牢固的,即JSON_CALLBACK,不要去做任何修改
这里只做简朴引见,项目中我们运用的是基于$http的$resource效劳,$resource依靠于$http。建立一个resource对象的工场函数,能够让你平安的和RESFUL效劳端举行数据交互。
须要注入 ngResource 模块。一样会有零丁模块引见。这里是衔接(待增加)。
延时器与计时器
J是中的setTimeout()和setInterval()这个人人一定不会生疏,在Angular中也有一样的效劳
$timeout 效劳
angular.module('myApp').controller('myCtrl', function($scope, $timeout) {
$scope.myHeader = "Hello World!";
$timeout(function () {
$scope.myHeader = "How are you today?";
}, 2000);
});
//要在模块中引入
$interval 效劳
angular.module('myApp').controller('myCtrl', function($scope, $timeout) {
$scope.theTime = new Date().toLocaleTimeString();
$interval(function () {
$scope.theTime = new Date().toLocaleTimeString();
}, 1000);
//时候绑定。
});
自定义效劳
建立自定义效劳
3种建立自定义效劳的体式格局。
- Factory
- Service
- Provider
之前也没有提到过,Angular这套框架最最先是由背景职员开辟的,运用了背景早就存在的分层头脑。所以项目也是运用这一设想情势。由此建立自定义效劳时用到了上述三种体式格局。
Factory
factory体式格局建立的效劳,作用就是返回一个有属性有要领的对象。
//经由过程工场情势建立自定义效劳
//一样能够注入依靠,但不能注入$scope作用域对象。
angular.module("MetronicApp").factory('myFactory', ['$resource','UrlConfig',function($resource,UrlConfig) {
var service = {};//定义一个Object对象'
service.name = "龙傲天";
service._getUrl = UrlConfig.url;
var age;//定义一个私有化的变量
//对私有属性写getter和setter要领
service.setAge = function(newAge){
age = newAge;
}
service.getAge = function(){
return age;
}
//原始需求概况
service.getUrl = function (id) {
return $resource(service._getUrl).get({orderId: id});
};
return service;//返回这个Object对象
}]);
//建立控制器
angular.module("MetronicApp").controller('myCtrl',['$scope', 'myFactory',function($scope, myFactory) {
$scope.name = myFactory.name;
myFactory.setAge(20);
$scope.age =myFactory.getAge();
myFactory.getUrl(id).$promise.then(function (result) {
scope.model = result.data;
});;
}]);
service
在service运用组织函数的要领去用它,在控制器中是以new的体式格局引入,所以能够挪用 service中定义的属性
//经由过程工场情势建立自定义效劳
//依靠注入其他模块
angular.module("MetronicApp").controller("myCtrl",['$scope'',myService',function($scope,myService){
$scope.name=myService.name;
myService.get(id).$promise.then(function (result) {
$scope.model = result.data;
});
}])
/*Service是new出来的,所以能够直接挪用内里的属性*/
angular.module("MetronicApp").service("myService",['$resource','UrlConfig',function($resource,UrlConfig){
this.name = '龙傲天';
this.url = UrlConfig.url;
this.get = function (id) {
return this.$resource(this._getUrl).get({orderId: id});
};
}])
Provider
假如想在 service 对象启用之前,先举行模块局限的设置,那就应当挑选 provider。
当你运用Provider建立一个自定义效劳时,能够经由过程$get()函数返回内容,唯一能够写进config设置阶段的一种。假如效劳,必需要在设置阶段实行,那末必需运用provider。
运用Provider的长处就是,你能够在Provider对象通报到运用程序的其他部份之前在app.config函数中对其举行修正。
//名字必需相符范例:myProvider(你的Provider效劳名字)+Provider
angular.module("MetronicApp").config(function(myProviderProvider){
myProviderProvider.name = "龙傲天"
})
//运用$get要领关联对应的config
angular.module("MetronicApp").provider("myProvider",['$resource','UrlConfig',function($resource,UrlConfig){
this.$get = function(){
return {
name : this.name,
age : 18,
url : UrlConfig.url ,
getData : function(id){
return this.$resource(UrlConfig.url).get({orderId: id});
}
}
}
}])
angular.module("MetronicApp").controller("myCtrl",['$scope','myProvider',function($scope,myProvider){
$scope.model = {
name : myProvider.name,
age : myProvider.age,
url : myProvider.url,
}
myProvider.getData(id).$promise.then(function (result) {
$scope.model.data = result.data;
});
}])
constant和value
运用constant和value要领建立效劳,常用于返回一个常量。
angular.module("MetronicApp").constant('$age', {
age: '18'
});
angular.module("MetronicApp").value('$name', {
name : '龙傲天'
});
angular.module("MetronicApp").controller('MyController', function($scope, $age, $name){
$scope.name = $name.name
$scope.USD = $age.age
})
过滤器中运用自定义效劳
angular.module("MetronicApp").service("myService",['UrlConfig',function(UrlConfig){
this.name = '龙傲天';
this.url = UrlConfig.url;
this.getUrl = function (url) {
var arr=url.split('/');
arr.push(this.url);
arr.push(this.name);
return arr.join('/')
}
}])
app.filter('myFilter',['myService', function(myService) {
return function(url) {
return myService.getUrl(url);
};
}]);
治理效劳的依靠
增加自定义效劳依靠项要领
我们在自定义效劳时,会依靠对象或效劳,有下面三种体式格局:
(1) 隐式声明
在参数中直接挪用,但这类体式格局在代码紧缩时注入的对象可能会失效
angular.module("MetronicApp").service("myService", function($resource,UrlConfigService) {
//code
})
(2) 挪用$inject属性
function myService($resource,UrlConfigService) {
//code
}
myService.$inject = ['$resource','UrlConfigService'];
angular.module('MetronicApp').service('myService', myService);
(3) 显式声明
在建立效劳的函数中,增加一个数组,在数组中按递次声明须要注入的效劳或对象称号,这类体式格局既高效也不会丧失代码,引荐运用(在上述实例中我们是用的都是此要领)
angular.module("MetronicApp").service("myService",['$resource','UrlConfig',function($resource,UrlConfig){
this.name = '龙傲天';
this.url = UrlConfig.url;
this.get = function (id) {
return this.$resource(this._getUrl).get({orderId: id});
};
}])
在angular的modul(模块)中注入效劳,也能够在定义modul时运用数组作为第二个参数,在此处把效劳注入进去,如许在函数体中运用不一致的效劳称号也是能够的,不过要确保注入的递次是一致的。(这个作为交叉,项目中能够运用定义的效劳称号,也能定义简化参数称号)注重此要领只针对显式声明有用。
angular.module("MetronicApp").controller("myCtrl",['$scope'',myDemandManageService',function($scope,myService){
//这里的myService就是指myDemandManageService;
$scope.name=myService.name;
myService.get(id).$promise.then(function (result) {
$scope.model = result.data;
});
}])
嵌套注入效劳
在Angular中,偶然须要将一个自定义的效劳注入到另一个自定义的效劳中,构成嵌套注入的情势,平常只须要将被注入的效劳作为内置效劳,采纳显式声明的体式格局注入即可。
// 运用factory定义confirm效劳
angular.module("MetronicApp").factory('confirm', ['$window', function ($win) {
return function (msg) {
$win.confirm(msg);
}
}]);
// 将confirm效劳显式的注入到fontWay效劳中
angular.module("MetronicApp").service('fontWay', ['$window', 'confirm', function ($win, con) {
return function (t, msg) {
return (t) ? con(msg) : $win.alert(msg);
}
}]);
angular.module("MetronicApp").controller('MyCtrl', ['$scope', 'fontWay', function ($scope, fontWay) {
$scope.ask = function (t, msg) {
fontWay(t, msg);
}
}])
效劳的其他设置
建立好的效劳平常比较复杂,假如后期须要修正,每每面对很高的风险,Angular为效劳增加了一些设置项,如装潢器(decorator),能够在不修正原代码的状况下为效劳增加其他功用。
效劳的装潢器(decorator)
装潢器(decorator)是Angular中内置效劳$provide所特有的一项设置函数,经由过程它能够阻拦效劳在实例化时建立的一些功用,并对原有功用举行优化和替换。
// 运用工场函数factory定义myService效劳
angular.module("MetronicApp").factory("myService", function () {
return {
name: '龙傲天',
age: 18
}
});
// 运用$provider的装潢器decorator为效劳myService扩大一个title属性
//症结的处所是在于decorator要领的回调函数的参数$delegate,指的是当前的数据(继续);项目中能够运用这个来做你想做的事变。
angular.module("MetronicApp").config(function ($provide) {
$provide.decorator('myService', function ($delegate) {
$delegate.title = 'CDS';
return $delegate;
})
});
angular.module("MetronicApp").controller('MyCtrl', function ($scope, myService) {
$scope.model = myService;
});
效劳是Angular的一个难点,人人能够先明白,在项目中参照上述实例做比较。。任重而道远啊。。