AngularJs功能(七)--服务

前端之家收集整理的这篇文章主要介绍了AngularJs功能(七)--服务前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

服务 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,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"},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',$timeout) {
    $scope.myHeader = "Hello World!";
    $timeout(function () {
       $scope.myHeader = "How are you today?";
    },2000);
});
//要在模块中引入

$interval 服务

angular.module('myApp').controller('myCtrl',$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',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',myService){  
  $scope.name=myService.name;
  myService.get(id).$promise.then(function (result) {
    $scope.model = result.data;
  });
}])

/*Service是new出来的,所以可以直接调用里面的属性*/
angular.module("MetronicApp").service("myService",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",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",'myProvider',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',$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",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",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",myDemandManageService',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','confirm',function ($win,con) {
  return function (t,msg) {
    return (t) ? con(msg) : $win.alert(msg);
  }
}]);
angular.module("MetronicApp").controller('MyCtrl','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',myService) {
  $scope.model = myService;
});

服务是Angular的一个难点,大家可以先理解,在项目中参照上述实例做比较。。任重而道远啊。。

猜你在找的Angularjs相关文章