AngularJs功能(七)--服务

发布时间:2019-06-08 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了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&amp;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) 显式声明

在创建服务的函数中,添加一个数组,在数组中按顺序声明需要注入的服务或对象名称,这种方式既高效也不会丢失代码,推荐使用(在上述实例中我们是用的都是此方法)

@H_512_1057@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的一个难点,大家可以先理解,在项目中参照上述实例做比较。。任重而道远啊。。

脚本宝典总结

以上是脚本宝典为你收集整理的AngularJs功能(七)--服务全部内容,希望文章能够帮你解决AngularJs功能(七)--服务所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。