GVKun编程网logo

Angular.js之服务与自定义服务学习笔记(解释angularjs中的服务是什么)

15

对于想了解Angular.js之服务与自定义服务学习笔记的读者,本文将是一篇不可错过的文章,我们将详细介绍解释angularjs中的服务是什么,并且为您提供关于4、AngularJS学习笔记–创建自定

对于想了解Angular.js之服务与自定义服务学习笔记的读者,本文将是一篇不可错过的文章,我们将详细介绍解释angularjs中的服务是什么,并且为您提供关于4、Angular JS 学习笔记 – 创建自定义指令 [翻译中]、angular – 使用另一个自定义服务的服务时没有提供…错误、angular 自定义服务、Angular.js自定义指令学习笔记实例的有价值信息。

本文目录一览:

Angular.js之服务与自定义服务学习笔记(解释angularjs中的服务是什么)

Angular.js之服务与自定义服务学习笔记(解释angularjs中的服务是什么)

<!DOCTYPE html>
<html lang="en">
<head>
<Meta charset="UTF-8">
<title>serviceAndDefinitService</title>

</head>
<body>
  <!--1:-->
  <div ng-app="myModule" ng-controller="ctrl">
    {{title}}<button ng-click="changeTitle()">change title</button>
    <button >change by jQuery</button>
  </div>

  <!--2:-->
  <div ng-app="module2" ng-controller="Ctrl2">
    {{name}}
    {{num}}
  </div>

  <!--4:-->
  <div ng-app="module3" ng-controller="Ctrl3">
    <div ng-bind="name"></div>
    <div ng-bind-html="name"></div>
  </div>

  <!--5:-->
  <div ng-app="module5">
    <div ng-controller="Ctrl5"></div>
  </div>

  <!--6:-->

  <table ng-app="module6" ng-controller="Ctrl6" border="1" width="400px" ng-cloak>
    <tr>
      <th>name</th>
      <th>age</th>
    </tr>
    <tr ng-repeat="v in data">
      <td>{{v.name}}</td>
      <td>{{v.age}}</td>
    </tr>
  </table>
  <script src="http://cdn.bootcss.com/angular.js/1.4.6/angular.js"></script>
  <script src="https://cdn.bootcss.com/jquery/1.8.3/jquery.js"></script>
  <script type="text/javascript">
    /*Angular.js之服务与自定义服务(服务:可以在多个应用场景下复用的代码片段)
    1:$scope.$apply()//在使用非$scope方法时需要调用angular.js的底层$apply()方法使$scope数据自动更新到view;
    2:$timeout与$interval服务,$timeout.cancel()取消延时器服务
    3:$window服务
    4:$sce服务安全的处理html数据,$trustAsHtml,view中需要加ng-bind-html属性;
    5:$cacheFactory缓存服务
    6:$http服务获取后台数据/$http服务缓存操作/$http服务简写操作/$http服务后台接收post数据
    7:使用factory自定义服务/多个控制器共享服务数据的处理
    8:使用service创建自定义服务*/

/*1:$scope.$apply()*/
  var m=angular.module('myModule',[]);
  m.controller('ctrl',['$scope',function($scope){
    $scope.title='puDong shop';
    //使用绑定到$scope上的方法更改$scope上的数据会自动更新视图
    $scope.changeTitle=function(){
    $scope.title='www.pudong.net';
  };
  //通过jQuery更改$scope数据时需要调用$apply()方法才能更新视图
    $('#btn').click(function(){
      $scope.title='www.pudong.com';
      $scope.$apply();
    });
 }])

/*2:$timeout与$interval服务*/
  var module2=angular.module('module2',[]);
  module2.controller('Ctrl2','$interval',function ($scope,$interval) {
    $scope.name="puDong store";
    $scope.num=1;
    $interval(function(){
      $scope.num++;
    },1000);
  }])

/*4:$sce服务安全的处理html数据,ng-bind-html;*/
  var module3=angular.module('module3',[]);
  module3.controller('Ctrl3','$sce',$sce) {
    $scope.name=$sce.trustAsHtml('<h1>This is URL of The puDong store !</h1>');
  }])

/*5:$cacheFactory缓存服务*/
  var module5=angular.module('module5',[]);
  module5.controller('Ctrl5','$cacheFactory',$cacheFactory) {
    //创建缓存容器,指定容器名称
    var obj=$cacheFactory('module5Mall');
    //写入缓存数据
    obj.put('title','puDong Store');
    obj.put('data',{'url':'http://www.pudong.com'});
    console.log(obj.get('title'));//puDong Store
    console.log(obj.get('data').url);//http://www.pudong.com
    //删除数据
    obj.remove('title');
    obj.removeAll();
    //销毁容器
    obj.destroy();
  }])

/*6:$http服务获取后台数据*/
  var module6=angular.module('module6',[]);
  module6.controller('Ctrl6','$http',$http) {
    $http({
      method:'get',
      url:'http://localhost/ajax.PHP',
      cache:true//$http服务缓存是使用$cacheFactory服务,只需要配置参数cache为true即可,当我们异步请求有个页面多次的时候,第一次的请求结果被缓存到页面中,后面的请求就不再发生,直接使用第一次的请求结果,
    }).then(function(response){
      $scope.data=response.data;
    },function(err){console.log(err);})
    //$http服务的简写:$http.get/post('',{}).then(function(){},function(){})第一个参数指定url,第二个参数指定其他配置选项
    $http.get('http://localhost/ajax.PHP',{
    cache:true
    }).then(function(){},function(){})
  }])

/*7:使用factory自定义服务/service自定义服务:service and factory的区别:factory时普通function,而service是一个构造器(constructor),Angular在调用service时会用new关键字,而调用factory时只是调用普通的function*/   var module6=angular.module('module6',[]);   //使用factory自定义服务   module6.factory('factoryService',['$http',function($http){     return {       get:function(){         return $http({url:'http://localhost/ajax.PHP'});       }     }   }])   //使用service自定义服务   module6.service('factoryService',function($http){     this.get=function(){       return $http({         method:'GET',        url:'http://localhost/ajax.PHP',      }).then(function(response){return response.data;},function(erro){return erro;})     }   }]);   module6.controller('Ctrl6','factoryService',factoryService) {     factoryService.get().then(function(response){       $scope.data=response.data;     })   }]) </script> </body> </html>

4、Angular JS 学习笔记 – 创建自定义指令 [翻译中]

4、Angular JS 学习笔记 – 创建自定义指令 [翻译中]

创建自定义指令

注意:本指南是针对已经熟悉AngularJS基础的开发者。如果您只是想要开始,建议您先去看教程。如果你在寻找指令的API,我们最近把他移动到 $compile

这个文档解释当我们想要在AngularJS 应用中建立自己的指令时,该如何实现。

什么是指令?

从一个高的层次看,指令是DOM元素(属性、元素名称、注释、或CSS样式类)上的标记告诉AngularJS的HTML 编译器($compile)去附加特定的行为到DOM元素或者是变换DOM元素和它的子元素。

Angular 内置了一个指令集,比如ngBind,ngModel,和ngClass。非常像是你创建一个Controllers和Services,你可以创建自己的指令用于Angular。当Angular穷的那个你的应用,HTML编译器通过DOM匹配指令。

“编译”HTML模板是什么意思?对于AngularJS,"编译" 表示附加事件到HTML上建立交互效果。我们使用“编译”这个术语的原因是指令的递归处理借鉴了编译程序语言编译源代码的过程。

匹配指令

我们写一个指令前,我们需要知道Angular的HTML编译器决定何时使用给定的指令。

在下面的例子中,我们说这个<input>元素匹配ngModel指令。

<input ng-model="foo">

下面的代码也匹配ngModel:

<input data-ng:model="foo">

标准化

Angular标准化一个元素的标签和属性名称去确定一个元素匹配哪个指令。我们通常引用指令通过区分大写小的驼峰标准名称(例如 ngModel)。不过,HTML是不区分大小写的,我们在DOM上引用指令通过小写方式,通常在元素上使用中划线分割属性名(例如 ng-model)。

标准化的过程如下:

  1. 从元素或者属性去除x-和data-前缀
  2. 转换带有分隔符:,-,或_的名称为驼峰格式:

举例来说,下面的方式是相同的都匹配ngBind指令。

<div ng-controller="Controller">
  Hello <input ng-model='name'> <hr/>
  <span ng-bind="name"></span> <br/>
  <span ng:bind="name"></span> <br/>
  <span ng_bind="name"></span> <br/>
  <span data-ng-bind="name"></span> <br/>
  <span x-ng-bind="name"></span> <br/>
</div>
angular.module('docsBindExample',[])
.controller('Controller',['$scope',function($scope) {
  $scope.name = 'Max Karl Ernst Ludwig Planck (April 23,1858 – October 4,1947)';
}]);
最佳时间:优先使用-分隔的格式。(例如 ng-bind对应 ngBind)。如果你想使用HTML验证工具,你可以替代使用data-为前缀的版本(例如 data-ng-bind对应 ngBind). 其他显示在上面的形式出于兼容的原因也是支持的,不过我们建议你避免使用。

指令的类型

$compile可以在元素名称,属性,样式类名称,甚至是注释上匹配指令。下面演示了不同方式的指令能够在模板中引用:

<my-dir></my-dir>
<span my-dir="exp"></span>
<!-- directive: my-dir exp -->
<span></span>
最佳实践:优先使用指令通过标签名、属性名,比注释和class名要好。所以一般就简单的提供一个元素匹配表示一个指令。
最佳实践:注释指令通常使用在DOM API 限制无法创建指令到多个元素的情况(例如内部的table元素)。AngularJS1.2 采用了ng-repeat-start 和 ng-repeat-end 更好的解决了这个问题。鼓励开发者尽可能的去使用这个在自定义的注视指令上。

文本和属性的绑定

在编译处理过程中,编译器使用$interpolate服务匹配文本和属性、查看是否包含嵌套的表达式。这些表达式注册为watches并且将局部更新作为普通编译周期的一部分,一个插值例子展示在下面:

<a ng-href="img/{{username}}.jpg">Hello {{username}}!</a>

ngAttr属性绑定

我们的浏览器有时候会更多的需要考虑有效的属性。

举例,就这个模板而言:

<svg>
  <circle cx="{{cx}}"></circle>
</svg>

我们大概期望Angular能够绑定,但是当我们检查控制台看到的类似于Errlr:Invalid value for attribute cx ="{{cx}}"。因为SVG DOM API 的约束,你不能简单的写作cx="{{cx}}"

用ng-attr-cx你可以绕过这个问题。

如果绑定的属性前缀是ngAttr(标准化之前的是ng-attr-),则在绑定过程中它将应用于相应的没有前缀的属性。这允许你绑定到属性,否则浏览器会着急的处理它(例如一个SVG元素的cricle[cx]属性)。当使用ngAttr,$interpolate的allOrnothing标记已经在使用,所以如果任何的表达式在插值字符串结果是undefined,则这个属性将会移除不会添加到元素。

举例子,我们可以修复上面的例子,写为:

<svg> <circle ng-attr-cx="{{cx}}"></circle> </svg>

如果你想要修改一个驼峰命名的属性(SVG元素具有有效的驼峰命名的属性),比如viewBox属性在svg元素,你可以使用下下划线去表示这个属性去绑定驼峰命名。

举例,去绑定viewBox,我们可以写成:

<svg ng-attr-view_Box="{{viewBox}}"> </svg>

创建指令

首先让我们说一下关于注册指令的API。非常像是控制器,指令也是注册在模块上。去注册一个指令,你使用module.directive API,module.directive需要一个标准的指令名称在工厂函数中。这个工厂函数应该返回一个基于不同选项的对象告诉$compile 当指令有匹配的时候如何做。

这个工厂函数在编译器第一次匹配指令的时候执行。你可以在这里执行任何的初始化工作。这个函数使用$injector.invoke执行使得它可以接受注入,类似于控制器。

最佳实践: Prefer using the deFinition object over returning a function.更好的是使用一个定义对象返回一个函数。

我们将通过一些指令的通用的例子,深入的了解不同的选项和编译过程。

最佳实践:为了避免某些未来的标准,最好给您的指令使用前缀。举个例子来说,如果你创建一个<carousel>指令,你可能会在HTML7引入的相同的元素发生而问题。2到3个短的前缀工作的很好。同样的,不要给自己的指令使用ng前缀或者你认为未来版本的angular可能会引起冲突的名称。

在下面的例子中,我们将使用前缀my(例如 myCustomer)。

模板扩展指令

假设你有一块表示客户信息的模板。这个模板在你的代码中重复了多次。当你修改一个地方,你需要去修改其他地方的几个。这是一个好机会使用一个指令去简化你的模板。

Let's create a directive that simply replaces its contents with a static template:

让我们创建一个静态的模板上的指令,简单的替换它的内容:

angular.module('docsSimpleDirective',function($scope) {
  $scope.customer = {
    name: 'Naomi',address: '1600 Amphitheatre'
  };
}])
.directive('myCustomer',function() {
  return {
    template: 'Name: {{customer.name}} Address: {{customer.address}}'
  };
});
<div ng-controller="Controller">
  <div my-customer></div>
</div>

Notice that we have bindings in this directive. After $compile compiles and links <div my-customer></div>,it will try to match directives on the element's children. This means you can compose directives of other directives. We'll see how to do that in an example below.

注意这样我们就做了指令的绑定。$comple编译和链接<div my-customer></div>之后,它将尝试去匹配指令到元素的子元素。这意味着你可以将多个指令组合起来。下我们将看到如何去做。

In the example above we in-lined the value of the template option,but this will become annoying as the size of your template grows.

在上面的例子中,我们将template选项的值写在了一行之中,但是这是我们为了使沉长的模板尺寸更好看。

最佳实践: Unless your template is very small,it's typically better to break it apart into its own HTML file and load it with the templateUrl option.除非你的模板很小,它通常最好拆分成几个HTML文件并且使用templateUrl属性来读取。

If you are familiar with ngInclude,templateUrl works just like it. Here's the same example using templateUrl instead:

如果你见过ngInclude,templateUrl的工作就和它是一样的。这里有一个相同的例子,使用templateUrl替代演示:

angular.module('docstemplateUrlDirective',function() {
  return {
    templateUrl: 'my-customer.html'
  };
});
<div ng-controller="Controller">
  <div my-customer></div>
</div>

templateUrl can also be a function which returns the URL of an HTML template to be loaded and used for the directive. Angular will call the templateUrl function with two parameters: the element that the directive was called on,and an attr object associated with that element.

templateUrl 也可以是一个函数来返回HTML模板的url,用来读取模板并且用于指令。Angular将调用templateUrl函数基于两个参数,一个是指令是在哪个元素上被调用,和一个attr属性关联相关的元素。

注意: You do not currently have the ability to access scope variables from the templateUrl function,since the template is requested before the scope is initialized.
你没有能力从templateUrl函数中访问scope中的变量,因为这个模板是在作用域初始化完毕前加载的。
angular.module('docstemplateUrlDirective',function() {
  return {
    templateUrl: function(elem,attr){
      return 'customer-'+attr.type+'.html';
    }
  };
});
<div ng-controller="Controller">
  <div my-customer type="name"></div>
  <div my-customer type="address"></div>
</div>
Name: {{customer.name}}
Address: {{customer.address}}
注意: When you create a directive,it is restricted to attribute and elements only by default. In order to create directives that are triggered by class name,you need to use the restrict option.当你创建一个指令,它将默认受限于属性和元素。为了创建指令将会根据class name触发,你必须使用restrict组合。

The restrict option is typically set to:

这些约束的选项通常有:

  • 'A' - only matches attribute name
  • A - 值匹配属性名
  • 'E' - only matches element name
  • E - 只匹配元素名称
  • 'C' - only matches class name
  • C - 只匹配css类名

These restrictions can all be combined as needed: 这些限制可以全部合并在需要的时候:

  • 'AEC' - matches either attribute or element or class name
  • AEC - 匹配属性、元素名称、或类名。

Let's change our directive to use restrict: 'E':

让我们修改我们的指令去使用restrict:'E';

angular.module('docsRestrictDirective',function() {
  return {
    restrict: 'E',templateUrl: 'my-customer.html'
  };
});
<div ng-controller="Controller">
  <my-customer></my-customer>
</div>

For more on the restrict property,see the API docs.

查看更多关于约束限制的属性,可以查看API 文档;

When should I use an attribute versus an element? Use an element when you are creating a component that is in control of the template. The common case for this is when you are creating a Domain-Specific Language for parts of your template. Use an attribute when you are decorating an existing element with new functionality.
什么时候我应该使用属性而不是元素?当你在模板中创建一个控制器的组件的时候,你应该使用元素。通常情况是当你创建一个特定领域的语言给你的模板。当你装饰一个已经存在的元素赋予更多的功能的时候,你应该使用属性。

Using an element for the myCustomer directive is clearly the right choice because you're not decorating an element with some "customer" behavior; you're defining the core behavior of the element as a customer component.

使用一个元素去对应myCustomer指令是一个显然正确的选择,因为你没有装饰一个元素一些“customer”的行为;你定义了customer组件的核心行为。

指令的作用域隔离

Our myCustomer directive above is great,but it has a fatal flaw. We can only use it once within a given scope.

我们的myCustomer指令很棒,但是它有一个致命的缺陷,我们只能在指定的作用域中使用它一次。

In its current implementation,we'd need to create a different controller each time in order to re-use such a directive:

现在的实现方式,为了重复使用我们的指令,我们必须每次创建不同的控制器。

angular.module('docsScopeProblemExample',[])
.controller('NaomiController',address: '1600 Amphitheatre'
  };
}])
.controller('IgorController',function($scope) {
  $scope.customer = {
    name: 'Igor',address: '123 Somewhere'
  };
}])
.directive('myCustomer',templateUrl: 'my-customer.html'
  };
});
<div ng-controller="NaomiController">
  <my-customer></my-customer>
</div>
<hr>
<div ng-controller="IgorController">
  <my-customer></my-customer>
</div>

This is clearly not a great solution.

这显然不是一个好的解决办法。

What we want to be able to do is separate the scope inside a directive from the scope outside,and then map the outer scope to a directive's inner scope. We can do this by creating what we call an isolate scope. To do this,we can use a directive's scope option:

我们想要有效的分隔作用域内的指令,并且映射外面的作用域到一个指令的内部作用域,我们可以做到,通过创建创建成为隔离作用域。如果这样使用,我们将创建隔离的作用域。为了这个,我们可以使用作用域的scope选项:

angular.module('docsIsolateScopeDirective',function($scope) {
  $scope.naomi = { name: 'Naomi',address: '1600 Amphitheatre' };
  $scope.igor = { name: 'Igor',address: '123 Somewhere' };
}])
.directive('myCustomer',scope: {
      customerInfo: '=info'
    },templateUrl: 'my-customer-iso.html'
  };
});
<div ng-controller="Controller">
  <my-customer info="naomi"></my-customer>
  <hr>
  <my-customer info="igor"></my-customer>
</div>

Looking at index.html,the first <my-customer> element binds the info attribute to naomi,which we have exposed on our controller's scope. The second binds info to igor.

让我们看卡index.html,第一个元素是<my-customer>元素绑定了info属性到naomi,我们而且将他曝光在了我们的controller作用域。第二个绑定info到igor.

Let's take a closer look at the scope option:

我们近一点看看scope选项

//... scope: { customerInfo: '=info'
},
//...

The scope option is an object that contains a property for each isolate scope binding. In this case it has just one property:

scope 选项是一个对象,包含 每一个隔离的作用域板顶。这样它本身就只是一个属性。

  • Its name (customerInfo) corresponds to the directive's isolate scope property customerInfo.
  • 属性名(customerInfo)相当于指令的隔离作用域中的属性customerInfo。
  • Its value (=info) tells $compile to bind to the info attribute.
  • 它的值(=info)告诉$compile去绑定info属性。
Note: These =attr attributes in the scope option of directives are normalized just like directive names. To bind to the attribute in <div bind-to-this="thing">,you'd specify a binding of =bindToThis.
注意:这个 =attr属性在 scope选项 是一个标准化类似于指令的名称 .去绑定属性到 <div bind-to-this="thing">,你需要设置值为 =bindToThis.

For cases where the attribute name is the same as the value you want to bind to inside the directive's scope,you can use this shorthand Syntax:

举例当你想要绑定到作用域的属性名与值相同的话,你可以简写为以下的语法:

...
scope: {
  // same as '=customer'
  customer: '='
},...

Besides making it possible to bind different data to the scope inside a directive,using an isolated scope has another effect.除此之外,还使它可能去绑定不同的数据到指令的作用域。

We can show this by adding another property,vojta,to our scope and trying to access it from within our directive's template:

我们可以添加其他的属性:vojta,到我们的作用域,并且尝试在我们的指令中访问它。

angular.module('docsIsolationExample',address: '1600 Amphitheatre' };
  $scope.vojta = { name: 'Vojta',address: '3456 Somewhere Else' };
}])
.directive('myCustomer',templateUrl: 'my-customer-plus-vojta.html'
  };
});
<div ng-controller="Controller">
  <my-customer info="naomi"></my-customer>
</div>
Name: {{customerInfo.name}} Address: {{customerInfo.address}}
<hr>
Name: {{vojta.name}} Address: {{vojta.address}}

Notice that {{vojta.name}} and {{vojta.address}} are empty,meaning they are undefined. Although we defined vojta in the controller,it's not available within the directive.

注意{{vojta.name}}和{{vojta.address}}是空的,说明他们是undefined。虽然我们定义了vojta在控制器中,但是它在指令中是无效的。

As the name suggests,the isolate scope of the directive isolates everything except models that you've explicitly added to thescope: {} hash object. This is helpful when building reusable components because it prevents a component from changing your model state except for the models that you explicitly pass in.

顾名思义,指令的隔离作用域隔离了除模块中明确添加到scope对象的任何东西。这在构建可复用组件时很有用,因为它防止组件在修改你的model状态时只是你明确允许的哪些。

注意: normally,a scope prototypically inherits from its parent. An isolated scope does not. See the "Directive Definition Object - scope" section for more information about isolate scopes.
一般情况,一个作用域继承自它的父类,一个隔离的作用域则不继承。查看"DIrective DeFinition Object "了解更多关于隔离作用域的信息。
最佳实践: Use the scope option to create isolate scopes when making components that you want to reuse throughout your app.当你创建一个你希望能够在你的应用内复用的组件,使用scope选项去创建一个隔离作用域。

创建一个指令操作DOM

In this example we will build a directive that displays the current time. Once a second,it updates the DOM to reflect the current time.

在例子中,我们将创建一个指令来显示当前的时间。每一秒,它更新DOM显示当前时间。

Directives that want to modify the DOM typically use the link option. link takes a function with the following signature,function link(scope, element, attrs) { ... } where:

指令要修改DOM,通常使用link选项。link接受一个函数,是这个样子:function link(scope, attrs) { ... }

  • scope is an Angular scope object. 是angular作用域对象
  • element is the jqLite-wrapped element that this directive matches.是一个指令匹配到的那个jqLite包装后的元素
  • attrs is a hash object with key-value pairs of normalized attribute names and their corresponding attribute values. 是一个键值对对象,保存着属性的名称和值。

In our link function,we want to update the displayed time once a second,or whenever a user changes the time formatting string that our directive binds to. We will use the $interval service to call a handler on a regular basis. This is easier than using $timeout but also works better with end-to-end testing,where we want to ensure that all $timeouts have completed before completing the test. We also want to remove the $interval if the directive is deleted so we don't introduce a memory leak.

在我们的link函数,我们想每一秒更新显示一次时间,或者我们的指令能够处理任何时候用户修改时间的格式。我们将使用$interval服务规律的调用handler方法。这是一个比使用$timeout简单而且能更好的用于端到端的测试,因为我们要确保在完全测试前完成所有的$timeout调用。我们还希望如果指令删除的时候能够删除$interval避免内存泄漏。

angular.module('docsTimeDirective',function($scope) {
  $scope.format = 'M/d/yy h:mm:ss a';
}])
.directive('myCurrentTime',['$interval','datefilter',function($interval,datefilter) {

  function link(scope,element,attrs) {
    var format,timeoutId;

    function updateTime() {
      element.text(datefilter(new Date(),format));
    }

    scope.$watch(attrs.myCurrentTime,function(value) {
      format = value;
      updateTime();
    });

    element.on('$destroy',function() {
      $interval.cancel(timeoutId);
    });

    // start the UI update process; save the timeoutId for canceling
    timeoutId = $interval(function() {
      updateTime(); // update DOM
    },1000);
  }

  return {
    link: link
  };
}]);
<div ng-controller="Controller">
  Date format: <input ng-model="format"> <hr/>
  Current time is: <span my-current-time="format"></span>
</div>

There are a couple of things to note here. Just like the module.controller API,the function argument in module.directive is dependency injected. Because of this,we can use $interval and datefilter inside our directive's link function.

这里有一两件事需要注意。正像 module.controller API,module.directive的函数参数是依赖注入的。因为这样,我们能够在我们的指令内部link函数中使用$interval和 datefilter。

We register an event element.on('$destroy', ...). What fires this $destroy event?

我们注册一个事件 element.on('$destroy',...)。如何触发这个$destroy事件?

There are a few special events that AngularJS emits. When a DOM node that has been compiled with Angular's compiler is destroyed,it emits a $destroy event. Similarly,when an AngularJS scope is destroyed,it broadcasts a $destroy event to listening scopes.

这里有几个AngularJS触发的特殊事件。当一个DOM节点被angular编译后,销毁了,它会触发$destroy时间。同样的,当时一个AngularJS作用域销毁了,它将广播$destroy事件到监听的作用域。

By listening to this event,you can remove event listeners that might cause memory leaks. Listeners registered to scopes and elements are automatically cleaned up when they are destroyed,but if you registered a listener on a service,or registered a listener on a DOM node that isn't being deleted,you'll have to clean it up yourself or you risk introducing a memory leak.

基于监听这个事件,你可以删除事件监听器可能会引起内存泄漏。监听器注册在作用域和元素,当它们销毁的时候会被自动的清理,但是你要注册一个监听器到service或者注册一个监听器到DOM节点,并且不要删除。你将收拾干净或者引入一个内存泄漏问题。

最佳实践: Directives should clean up after themselves. You can use element.on('$destroy', ...) or scope.$on('$destroy', ...) to run a clean-up function when the directive is removed. 指令应该清理他们自身,你可以使用element.on('$destroy',...) 或者scope.$on('$destroy',...)去清理函数当指令删除的时候。

创建一个指令包含其他的元素

We've seen that you can pass in models to a directive using the isolate scope,but sometimes it's desirable to be able to pass in an entire template rather than a string or an object. Let's say that we want to create a "dialog Box" component. The dialog Box should be able to wrap any arbitrary content.

我们可以看到你能够通过一个模型给一个指令使用隔离的作用域,但是有些时候,它理想的是能够通过整个模板而不是一个字符串或者对象。让我们去创建一个“对话窗口”组件,这个对话窗口应该能够包含任何的内容。

To do this,we need to use the transclude option.

为此,我们要必须使用transclude选项。

angular.module('docsTransclusionDirective',function($scope) {
  $scope.name = 'Tobias';
}])
.directive('myDialog',transclude: true,templateUrl: 'my-dialog.html'
  };
});
<div ng-controller="Controller">
  <my-dialog>Check out the contents,{{name}}!</my-dialog>
</div>

What does this transclude option do,exactly? transclude makes the contents of a directive with this option have access to the scopeoutside of the directive rather than inside.

trasclude选项到底做了什么?transclude标记一个指令中的内容基于这个选项可以访问这个指令以外的作用域。

To illustrate this,see the example below. Notice that we've added a link function in script.js that redefines name as Jeff. What do you think the {{name}} binding will resolve to Now?

为了演示,我们看下面的例子。注意我们添加了一个link函数到script.js重新定义了name为Jeff。你认为{{name}}现在被绑定到哪个值上了呢?

angular.module('docsTransclusionExample',scope: {},templateUrl: 'my-dialog.html',link: function (scope,element) {
      scope.name = 'Jeff';
    }
  };
});
<div ng-controller="Controller">
  <my-dialog>Check out the contents,{{name}}!</my-dialog>
</div>

Ordinarily,we would expect that {{name}} would be Jeff. However,we see in this example that the {{name}} binding is still Tobias.

一般情况下我们预计{{name}}应该是Jeff。不过,我们在例子汇总看到的是{{name}}仍然是Tobias。

The transclude option changes the way scopes are nested. It makes it so that the contents of a transcluded directive have whatever scope is outside the directive,rather than whatever scope is on the inside. In doing so,it gives the contents access to the outside scope.

这个transclude选项更改作用域嵌套。它标记转换后的指令里的内容无论如何会使用外部的作用域,而不是内部的作用域。在这样的情况下,它让内容访问的是外部的作用域。

Note that if the directive did not create its own scope,then scope in scope.name = 'Jeff'; would reference the outside scope and we would see Jeff in the output.

注意,如果这个指令没有创建它自己的作用域,然后将在作用域中设置scope.name='Jeff';它将引用外部的作用域,我们将在输出中看到Jeff。

This behavior makes sense for a directive that wraps some content,because otherwise you'd have to pass in each model you wanted to use separately. If you have to pass in each model that you want to use,then you can't really have arbitrary contents,can you?

指令的这种行为是合理的,它包装一些内容,否则你将不得不在每一个模型中传递。如果你不得不在你想要的每个模型中传递,那你将不能真正随心所欲的写内容,你能吗?

最佳实践: only use transclude: true when you want to create a directive that wraps arbitrary content. 只有当你想创建一个指令想自由的控制内容时,你才使用transclude:true.

Next,we want to add buttons to this dialog Box,and allow someone using the directive to bind their own behavior to it.

另外,我们希望添加一个按钮到这个弹出窗口,并且允许使用这个指令去绑定自己的行为。

angular.module('docsIsoFnBindExample','$timeout',function($scope,$timeout) {
  $scope.name = 'Tobias';
  $scope.message = '';
  $scope.hideDialog = function (message) {
    $scope.message = message;
    $scope.dialogIsHidden = true;
    $timeout(function () {
      $scope.message = '';
      $scope.dialogIsHidden = false;
    },2000);
  };
}])
.directive('myDialog',scope: {
      'close': '&onClose'
    },templateUrl: 'my-dialog-close.html'
  };
});
<div ng-controller="Controller">
  {{message}}
  <my-dialog ng-hide="dialogIsHidden" on-close="hideDialog(message)">
    Check out the contents,{{name}}!
  </my-dialog>
</div>

We want to run the function we pass by invoking it from the directive's scope,but have it run in the context of the scope where it's registered.

我们希望运行的函数通过指令的作用域来执行,而且要让他它在注册过的上下文中执行。

We saw earlier how to use =attr in the scope option,but in the above example,we're using &attr instead. The & binding allows a directive to trigger evaluation of an expression in the context of the original scope,at a specific time. Any legal expression is allowed,including an expression which contains a function call. Because of this,& bindings are ideal for binding callback functions to directive behaviors.

我们看到之前如何使用=attr在scope选项中,但是在上面的例子中,我们使用$attr替代。这种&绑定允许一个指令在特定的时间触发在原始的作用域中的表达式求值。任何合法的表达式都允许,包括函数调用的表达式。因此,&绑定是一个理想的用来给指令的行为绑定回调函数的方法。

When the user clicks the x in the dialog,the directive's close function is called,thanks to ng-click. This call to close on the isolated scope actually evaluates the expression hideDialog(message) in the context of the original scope,thus running Controller'shideDialog function.

接下来我们点击窗口中的x,这个指令的close函数被调用。感谢ng-click。这次调用close在隔离的作用的域实际上是表达式hideDialog(meesage),我们运行Controller的hideDialog函数。

Often it's desirable to pass data from the isolate scope via an expression to the parent scope,this can be done by passing a map of local variable names and values into the expression wrapper fn. For example,the hideDialog function takes a message to display when the dialog is hidden. This is specified in the directive by calling close({message: 'closing for Now'}). Then the local variable message will be available within the on-close expression.

通常从隔离的作用域通过表达式获取父级数据,它可以通过一个本地变量的name和value组成的map放到表达式包装的函数。拿例子来说,hideDialog函数取得一个message在dialog隐藏的时候显示。这个指定在指令中叫close({message:'closing for Now'}),然后这个本地变量mesage将在on-close表达式中可用。

最佳实践: use &attr in the scope option when you want your directive to expose an API for binding to behaviors. 当你想要你的指令暴露一个绑定行为的API的时候,使用&attr在scope选项中。

创建一个指令添加事件监听器

PrevIoUsly,we used the link function to create a directive that manipulated its DOM elements. Building upon that example,let's make a directive that reacts to events on its elements.

For instance,what if we wanted to create a directive that lets a user drag an element?

angular.module('dragModule',[])
.directive('myDraggable',['$document',function($document) {
  return function(scope,attr) {
    var startX = 0,startY = 0,x = 0,y = 0;

    element.css({
     position: 'relative',border: '1px solid red',backgroundColor: 'lightgrey',cursor: 'pointer'
    });

    element.on('mousedown',function(event) {
      // Prevent default dragging of selected content
      event.preventDefault();
      startX = event.pageX - x;
      startY = event.pageY - y;
      $document.on('mousemove',mousemove);
      $document.on('mouseup',mouseup);
    });

    function mousemove(event) {
      y = event.pageY - startY;
      x = event.pageX - startX;
      element.css({
        top: y + 'px',left:  x + 'px'
      });
    }

    function mouseup() {
      $document.off('mousemove',mousemove);
      $document.off('mouseup',mouseup);
    }
  };
}]);
<span my-draggable>Drag ME</span>

创建指令沟通

You can compose any directives by using them within templates.

Sometimes,you want a component that's built from a combination of directives.

Imagine you want to have a container with tabs in which the contents of the container correspond to which tab is active.

angular.module('docsTabsExample',[])
.directive('myTabs',controller: function($scope) {
      var panes = $scope.panes = [];

      $scope.select = function(pane) {
        angular.forEach(panes,function(pane) {
          pane.selected = false;
        });
        pane.selected = true;
      };

      this.addPane = function(pane) {
        if (panes.length === 0) {
          $scope.select(pane);
        }
        panes.push(pane);
      };
    },templateUrl: 'my-tabs.html'
  };
})
.directive('myPane',function() {
  return {
    require: '^myTabs',restrict: 'E',scope: {
      title: '@'
    },link: function(scope,attrs,tabsCtrl) {
      tabsCtrl.addPane(scope);
    },templateUrl: 'my-pane.html'
  };
});
<my-tabs>
  <my-pane title="Hello">
    <h4>Hello</h4>
    <p>Lorem ipsum dolor sit amet</p>
  </my-pane>
  <my-pane title="World">
    <h4>World</h4>
    <em>Mauris elementum elementum enim at suscipit.</em>
    <p><a href ng-click="i = i + 1">counter: {{i || 0}}</a></p>
  </my-pane>
</my-tabs>
<div>
  <ul>
    <li ng-repeat="pane in panes" ng->
      <a href="" ng-click="select(pane)">{{pane.title}}</a>
    </li>
  </ul>
  <divng-transclude></div>
</div>
<divng-show="selected" ng-transclude>
</div>

The myPane directive has a require option with value ^myTabs. When a directive uses this option,$compile will throw an error unless the specified controller is found. The ^ prefix means that this directive searches for the controller on its parents (without the ^ prefix,the directive would look for the controller on just its own element).

So where does this myTabs controller come from? Directives can specify controllers using the unsurprisingly named controller option. As you can see,the myTabs directive uses this option. Just like ngController,this option attaches a controller to the template of the directive.

If it is necessary to reference the controller or any functions bound to the controller's scope in the template,you can use the optioncontrollerAs to specify the name of the controller as an alias. The directive needs to define a scope for this configuration to be used. This is particularly useful in the case when the directive is used as a component.

Looking back at myPane's deFinition,notice the last argument in its link function: tabsCtrl. When a directive requires a controller,it receives that controller as the fourth argument of its link function. Taking advantage of this,myPane can call the addPane function ofmyTabs.

If multiple controllers are required,the require option of the directive can take an array argument. The corresponding parameter being sent to the link function will also be an array.

angular.module('docsTabsExample',[])
.directive('myPane',function() {
  return {
    require: ['^myTabs','^ngModel'],controllers) {
      var tabsCtrl = controllers[0],modelCtrl = controllers[1];

      tabsCtrl.addPane(scope);
    },templateUrl: 'my-pane.html'
  };
});

Savvy readers may be wondering what the difference is between link and controller. The basic difference is that controller can expose an API,and link functions can interact with controllers using require.

最佳实践: use controller when you want to expose an API to other directives. Otherwise use link.

总结

Here we've seen the main use cases for directives. Each of these samples acts as a good starting point for creating your own directives.

You might also be interested in an in-depth explanation of the compilation process that's available in the compiler guide.

The $compile API page has a comprehensive list of directive options for reference.

tips:

本文由wp2Blog导入,原文链接:http://devonios.com/4%e3%80%81angular-js-%e5%ad%a6%e4%b9%a0%e7%ac%94%e8%ae%b0-directives.html

angular – 使用另一个自定义服务的服务时没有提供…错误

angular – 使用另一个自定义服务的服务时没有提供…错误

所以,我们谈论的是angular2,我知道它仍处于alpha状态.
我创建了一个我将在另一个服务中使用的基本服务.然后将后者用于组件中.

基本服务看起来像这样

import {Injectable,Observable} from 'angular2/core';
import {Http} from 'angular2/http';
import {RequestOptionsArgs,Connection,ConnectionBackend} from 'angular2/http';
import {BaseRequestOptions,RequestOptions} from 'angular2/http';
import {RequestMethods} from 'angular2/http';
import {Response} from 'angular2/http';
import {Request} from 'angular2/http';
import {makeTypeError} from 'angular2/src/facade/exceptions';

@Injectable()

export class MyOAuth extends Http {
  constructor(backend: ConnectionBackend,defaultOptions: RequestOptions) {
    super(backend,defaultOptions);
  }

  /**
   * Performs any type of http request. First argument is required,and can either be a url or
   * a {@link Request} instance. If the first argument is a url,an optional {@link RequestOptions}
   * object can be provided as the 2nd argument. The options object will be merged with the values
   * of {@link BaseRequestOptions} before performing the request.
   */
  request(url: string | Request,options?: RequestOptionsArgs): Observable<Response> {
    var responSEObservable: any;
    if (isstring(url)) {
      responSEObservable = httpRequest(
          this._backend,new Request(mergeOptions(this._defaultOptions,options,RequestMethods.Get,url)));
    } else if (url instanceof Request) {
      responSEObservable = httpRequest(this._backend,url);
    } else {
      throw makeTypeError('First argument must be a url string or Request instance.');
    }
    return responSEObservable;
  }
}

使用上述服务的其他服务看起来像这样(authenticate.js):

import {Injectable,Inject} from 'angular2/angular2';
import {MyOAuth} from './MyOAuth';


@Injectable()

export class AuthenticationService {

  constructor(@Inject(MyOAuth) http) {
    this.http = http;
  }

  authenticate(username,password,community) {
    console.log('authenticate');
  }
}

然后在课堂上使用这个服务我称之为:

import {Page} from 'ionic/ionic';
import './login.scss';
import {AuthenticationService} from '../../services/authentication';

@Page({
  templateUrl: 'app/login/login.html',providers: [AuthenticationService] //As of alpha 42
})

我在浏览器中得到的错误是

EXCEPTION: No provider for MyOAuth! (LoginPage -> AuthenticationService -> MyOAuth)

对我来说,我必须导入MyOAuth …

解决方法

当您需要将自定义服务注入其他服务时,您需要在更大的上下文(组件,页面,应用程序)中提供服务

你可以做:

import {Page} from 'ionic/ionic';
import './login.scss';
import {AuthenticationService} from '../../services/authentication';

@Page({
    templateUrl: 'app/login/login.html',providers: [[AuthenticationService],[MyOAuth]]
})

对我来说,如果服务可以在多个地方重用,我总是在应用程序上下文中定义它.例如:

@Component({
    templateUrl: 'build/app.html',[MyOAuth]]
})
class MyApp{
}

所以这些服务只会被安置一次.如果你提供它们,例如:Page1,Page2,它们将被实例化两次

angular 自定义服务

angular 自定义服务

AngularJS支持使用服务的体系结构“关注点分离”的概念。服务是JavaScript函数,并负责只做一个特定的任务。这也使得他们即维护和测试的单独实体。控制器,过滤器可以调用它们作为需求的基础。服务使用AngularJS的依赖注入机制注入正常。

AngularJS提供例如许多内在的服务,如:$http,$route,$window,$location等。每个服务负责例如一个特定的任务,$http是用来创建AJAX调用,以获得服务器的数据。 $route用来定义路由信息等。内置的服务总是前缀$符号。

有两种方法来创建服务。

  1. 工厂
  2. 服务

使用工厂方法

使用工厂方法,我们先定义一个工厂,然后分配方法给它。

   var mainApp = angular.module("mainApp",[]);
   mainApp.factory('MathService',function() {   
     var factory = {}; 
     factory.multiply = function(a,b) {
      return a * b 
     }
     return factory;
   }); 

使用服务方法

使用服务的方法,我们定义了一个服务,然后分配方法。还注入已经可用的服务。

mainApp.service('CalcService',function(MathService){ this.square = function(a) { return MathService.multiply(a,a); } });

例子

下面的例子将展示上述所有指令。
testAngularJS.html

<html> <head> <title>Angular JS Forms</title> </head> <body> <h2>AngularJS Sample Application</h2> <div ng-app="mainApp" ng-controller="CalcController"> <p>Enter a number: <input type="number" ng-model="number" /> <button ng-click="square()">X<sup>2</sup></button> <p>Result: {{result}}</p> </div> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script> <script> var mainApp = angular.module("mainApp",b) { return a * b } return factory; }); mainApp.service('CalcService',function(MathService){ this.square = function(a) { return MathService.multiply(a,a); } }); mainApp.controller('CalcController',function($scope,CalcService) { $scope.square = function() { $scope.result = CalcService.square($scope.number); } }); </script> </body> </html>

Angular.js自定义指令学习笔记实例

Angular.js自定义指令学习笔记实例

本文给大家分享angular.js学习笔记之自定义指令实例代码讲解,具体代码如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularDirective</title>
<script src="http://cdn.bootcss.com/angular.js/1.4.6/angular.js"></script>
</head>
<body ng-app="angularJS" >
<!-- <div>{{title}}<input type="text" ng-model=''title''></div> -->
<!-- <input type="text" ng-model="color">
<self-direct color=''{{color}}''></self-direct>
<self-direct m-color=''{{color}}''></self-direct> -->
<!-- <input type="text" ng-model="color">
<self-direct color=''color''></self-direct>如果采用双向绑定,指令中的属性值默认是变量,所以不用添加{{}}
<self-direct m-color=''color''></self-direct> -->
<!-- <self-direct logo=''logo()''></self-direct> -->
<!-- <self-direct ></self-direct> -->
<!-- <self-direct ></self-direct> -->
<self-direct title="JinDong" bgcolor="red" fontcolor="#fff"></self-direct>
<script type="text/javascript">
/*Angular.js自定义指令的格式和相关参数与其值:
let m=angular.module(''angularJS'',[]);
m.directive(''selfDirect'',[function(){//selfDirect表示自定义指令的名字,采用驼峰命名法,当restrict的值为E的时候:<self-direct></self-direct>
return {
restrict:''A/E/C'',//A:Attrabute,E:Elements,C:class;restrict属性表示生成指令在页面中的表现形式,字母必须大写,不建议使用C,因为C的写法与CSS耦合性太强.
template:''<p>template选项表示指令在页面中显示的内容,template的值可以是字符串也可以是HTML的标签形式,也可以为函数,如:template:function(elle,attr){return ''<span>''+ele.html()+''</span>''},view内容太多的时候不建议使用函数的形式</p>'',
replace:true,//使用模板内容替换包含模板内容的父级标签
transclude:true,//其内容填充到ng-transclude指定的位置
templateUrl:'''',//不可与template同时使用
scope:true,//默认为false,设置指令的作用域,当值为{}时,模板中的变量不会继承来自控制器中的属性值,
controller:[''$scope'',function($scope){$scope.data={...}}],//指令中的控制器
link:function(scope,elem,attr){},//用link完成对DOM的操作,scope:指令的作用域,elem:指令标签元素,attr:指令标签元素的属性数组,
};
}])
*/
var m=angular.module(''angularJS'',[]);
m.directive(''selfDirect'', [function () {
return {
restrict: ''E'',
//template:''<h1><span ng-transclude=""></span>This is a Angular.js direction of self definition</h1><div ng-transclude=""></div>'',
//replace:true,
//transclude:true,
//templateUrl:''viewModel.html'',
//scope:{},
//template:''{{title}}<input type="text" ng-model="title">'', 
//template:''<p>suNing store</p><input ng-model="color">'',
//scope:{color:''@mColor''},//控制器和指令隔离作用域@单项文本绑定,控制器可以影响指令中的数据,而指令不能影响控制器中的数据
//scope:{color:''=mColor''},//控制器和指令隔离作用域=双向文本绑定,控制器可以影响指令中的数据,指令也可以影响控制器中的data
//template:''<p>{{logo()}}</p>'',
//scope:{logo:''&''},//用&符号调用父控制器中的方法
/*replace:true,
templateUrl:''viewModel.html'',
controller:[''$scope'',function($scope){
$scope.data=[{
id:1,title:''puDong''
},{
id:2,title:''JinDong''
},{
id:3,title:''TianMao''
}];
}],*/
scope:{title:''@''},
link:function(scope,elem,attr){
$(elem).css({
backgroundColor:attr[''bgcolor''],
color:attr[''fontcolor'']
}).html(scope.title);
},
};
}]);
/*m.controller(''ctrl'',[''$scope'',function($scope){
$scope.title=''SuNing store'';
$scope.color=''red'';
$scope.logo=function(){
return ''TianMao store'';
};
}]);*/
</script>
</body>
</html>

以上所述是小编给大家介绍的Angular.js自定义指令的实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!

您可能感兴趣的文章:
  • Angular1.x自定义指令实例详解
  • Angular之指令Directive用法详解
  • 详解Angular.js指令中scope类型的几种特殊情况
  • angular分页指令操作
  • AngularJS内置指令
  • AngularJS学习笔记之基本指令(init、repeat)
  • AngularJS中的指令全面解析(必看)
  • 用AngularJS的指令实现tabs切换效果
  • 深入讲解AngularJS中的自定义指令的使用
  • Angularjs编写KindEditor,UEidtor,jQuery指令
  • 自定义Angular指令与jQuery实现的Bootstrap风格数据双向绑定的单选与多选下拉框
  • Angular1.x复杂指令实例详解

关于Angular.js之服务与自定义服务学习笔记解释angularjs中的服务是什么的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于4、Angular JS 学习笔记 – 创建自定义指令 [翻译中]、angular – 使用另一个自定义服务的服务时没有提供…错误、angular 自定义服务、Angular.js自定义指令学习笔记实例等相关知识的信息别忘了在本站进行查找喔。

本文标签: