首页 web前端 js教程 理解AngularJs指令_AngularJS

理解AngularJs指令_AngularJS

May 16, 2016 pm 03:26 PM
angularjs 指令

对于指令,可以把它简单的理解成在特定DOM元素上运行的函数,指令可以扩展这个元素的功能。

首先来看个完整的参数示例再来详细的介绍各个参数的作用及用法:

angular.module('myApp', []) 
.directive('myDirective', function() { 
  return { 
    restrict: String, 
    priority: Number, 
    terminal: Boolean, 
    template: String or Template Function: 
  function(tElement, tAttrs) {...}, 
  templateUrl: String, 
  replace: Boolean or String, 
  scope: Boolean or Object, 
  transclude: Boolean, 
  controller: String or 
  function(scope, element, attrs, transclude, otherInjectables) { ... }, 
  controllerAs: String, 
  require: String, 
  link: function(scope, iElement, iAttrs) { ... }, 
  compile: // 返回一个对象或连接函数,如下所示:
  function(tElement, tAttrs, transclude) { 
    return { 
      pre: function(scope, iElement, iAttrs, controller) { ... }, 
      post: function(scope, iElement, iAttrs, controller) { ... } 
      } 
    return function postLink(...) { ... } 
    } 
  }; 
 });
登录后复制

1、restrict[string]

restrict是一个可选的参数。用于指定该指令在DOM中以何种形式被声明。默认值是A,即以属性的形式来进行声明。
可选值如下:
E(元素)


A(属性,默认值)


C(类名)


M(注释)

<--directive:my-directive expression-->
一般考虑到浏览器的兼容性,强烈建议使用默认的属性就可以即即以属性的形式来进行声明。最后一种方式建议再不要求逼格指数的时候千万不要用。

Code:

 angular.module('app',[])
  .directive('myDirective', function () {
      return { 
        restrict: 'E', 
        template: '<a href="http://www.baidu.com">百度</a>' 
      };
    })
HtmlCode:
 <my-directive></my-directive>
登录后复制

效果:

2、priority[int]

大多数指令会忽略这个参数,使用默认值0,但也有些场景设置高优先级是非常重要甚至是必须的。例如,ngRepeat将这个参数设置为1000,这样就可以保证在同一元素上,它总是在其他指令之前被调用。

3、terminal[bool]

这个参数用来停止运行当前元素上比本指令优先级低的指令。但同当前指令优先级相同的指令还是会被执行。
例如:ngIf的优先级略高于ngView(它们操控的实际就是terminal参数),如果ngIf的表达式值为true,ngView就可以被正常执行,但如果ngIf表达式的值为false,由于ngView的优先级较低就不会被执行。

4、template[string or function]

template参数是可选的,必须被设置为以下两种形式之一:

  • 一段HTML文本;
  • 一个可以接受两个参数的函数,参数为tElement和tAttrs,并返回一个代表模板的字符串。tElement和tAttrs中的t代表template,是相对于instance的。

首先演示下第二种用法:

angular.module('app',[])
  .directive('myDirective', function () {
      return { 
        restrict: 'EAC', 
        template: function (elem, attr) {
          return "<a href='" + attr.value + "'>" + attr.text + "</a>";
        }
    };
  })
登录后复制

HtmlCode:(效果同上,不做演示了)

<my-directive value="http://www.baidu.com" text="百度"></my-directive>
    <div my-directive
       value="http://www.baidu.com"
       text="百度"></div>
登录后复制

5、templateUrl[string or function]

templateUrl是可选的参数,可以是以下类型:

  • 一个代表外部HTML文件路径的字符串;
  • 一个可以接受两个参数的函数,参数为tElement和tAttrs,并返回一个外部HTML文件路径的字符串。

无论哪种方式,模板的URL都将通过ng内置的安全层,特别是$getTrustedResourceUrl,这样可以保护模板不会被不信任的源加载。 默认情况下,调用指令时会在后台通过Ajax来请求HTML模板文件。加载大量的模板将严重拖慢一个客户端应用的速度。为了避免延迟,可以在部署应用之前对HTML模板进行缓存。

Code:

 angular.module('app',[])
  .directive('myDirective', function () {
      return { 
        restrict: 'AEC', 
        templateUrl: function (elem, attr) {
          return attr.value + ".html"; //当然这里我们可以直接指定路径,同时在模板中可以包含表达式
        }
    };
  })
登录后复制

6、replace[bool]

replace是一个可选参数,如果设置了这个参数,值必须为true,因为默认值为false。默认值意味着模板会被当作子元素插入到调用此指令的元素内部,
例如上面的示例默认值情况下,生成的html代码如下:

<my-directive value="http://www.baidu.com" text="百度"><a href="http://www.baidu.com">百度</a></my-directive>
登录后复制

如果设置replace=true

<a href="http://www.baidu.com" value="http://www.baidu.com" text="百度">百度</a>

登录后复制

据我观察,这种效果只有设置restrict="E"的情况下,才会表现出实际效果。

介绍完基本的指令参数后,就要涉及到更重要的作用域参数了...

7、scope参数[bool or object]

scope参数是可选的,可以被设置为true或一个对象。默认值是false。

如果一个元素上有多个指令使用了隔离作用域,其中只有一个可以生效。只有指令模板中的根元素可以获得一个新的作用域。因此,对于这些对象来说scope默认被设置为true。内置指令ng-controller的作用,就是从父级作用域继承并创建一个新的子作用域。它会创建一个新的从父作用域继承而来的子作用域。这里的继承就不在赘述,和面向对象中的继承基本是一直的。

首先我们来分析一段代码:

 <div ng-app="app" ng-init="name= '祖父'">
      <div ng-init="name='父亲'">
        第一代:{{ name }}
        <div ng-init="name= '儿子'" ng-controller="SomeController">
          第二代: {{ name }}
          <div ng-init="name='孙子'">
            第三代: {{ name }}
          </div>
        </div>
      </div>
    </div> 
登录后复制

我们发现第一代,我们初始化name为父亲,但是第二代和第三代其实是一个作用域,那么他们的name其实是一个对象,因此出现的效果如下:

第一代:父亲
第二代: 孙子
第三代: 孙子
我们在修改一下代码,把第三代隔离开来再看看效果:

<div ng-app="app"ng-init="name= '祖父'">
      <div ng-init="name='父亲'">
        第一代:{{ name }}
        <div ng-init="name= '儿子'" ng-controller="SomeController">
          第二代: {{ name }}
          <div ng-init="name='孙子'" ng-controller="SecondController">
            第三代: {{ name }}
          </div>
        </div>
      </div>
    </div>
登录后复制

JsCode:

 angular.module('app', [])
    .controller('SomeController',function($scope) {
      
    })
    .controller('SecondController', function ($scope) {
    
  }) 
登录后复制

效果如下:

第一代:父亲
第二代: 儿子
第三代: 孙子
在修改下代码来看看继承:

    <div ng-app="app"ng-init="name= '祖父的吻'">
      <div>
        第一代:{{ name }}
        <div ng-controller="SomeController">
          第二代: {{ name }}
          <div ng-controller="SecondController">
            第三代: {{ name }}
          </div>
        </div>
      </div>
    </div> 
登录后复制

效果如下:

第一代:祖父的吻
第二代: 祖父的吻
第三代: 祖父的吻

如果要创建一个能够从外部原型继承作用域的指令,将scope属性设置为true,简单来说就是可继承的隔离,即不能反向影响父作用域。

再来看个例子:

  angular.module('myApp', [])
    .controller('MainController', function ($scope) {
    })
    .directive('myDirective', function () {
      return {
        restrict: 'A',
        scope:false,//切换为{},true测试
        priority: 100,
        template: '<div>内部:{{ myProperty }}<input ng-model="myProperty"/></div>'
      };
    });
登录后复制

Html代码:

 <div ng-controller='MainController' ng-init="myProperty='Hello World!'">
    外部: {{ myProperty}}
    <input ng-model="myProperty" />
    <div my-directive></div>
  </div>
登录后复制

当我们改变scope的值我们会发现

false:继承但不隔离

true:继承并隔离

{}:隔离且不继承

8、transclude

transclude是一个可选的参数。默认值是false。嵌入通常用来创建可复用的组件,典型的例子是模态对话框或导航栏。我们可以将整个模板,包括其中的指令通过嵌入全部传入一个指令中。指令的内部可以访问外部指令的作用域,并且模板也可以访问外部的作用域对象。为了将作用域传递进去,scope参数的值必须通过{}或true设置成隔离作用域。如果没有设置scope参数,那么指令内部的作用域将被设置为传入模板的作用域。

只有当你希望创建一个可以包含任意内容的指令时,才使用transclude: true。

我们来看两个例子-导航栏:

<div side-box title="TagCloud">
    <div class="tagcloud">
      <a href="">Graphics</a>
      <a href="">ng</a>
      <a href="">D3</a>
      <a href="">Front-end</a>
      <a href="">Startup</a>
    </div>
  </div>
登录后复制

JsCode:

 angular.module('myApp', []) 
 .directive('sideBox', function() { 
   return { 
     restrict: 'EA', 
     scope: { 
       title: '@' 
     }, 
     transclude: true, 
     template: '<div class="sidebox"><div class="content"><h2 class="header">' +
       '{{ title }}</h2><span class="content" ng-transclude></span></div></div>' 
     }; 
  }); 
登录后复制

这段代码告诉ng编译器,将它从DOM元素中获取的内容放到它发现ng-transclude指令的地方。

再来你看个官网的例子:

angular.module('docsIsoFnBindExample', [])
 .controller('Controller', ['$scope', '$timeout', function($scope, $timeout) {
  $scope.name = 'Tobias';
  $scope.hideDialog = function () {
   $scope.dialogIsHidden = true;
   $timeout(function () {
    $scope.dialogIsHidden = false;
   }, 2000);
  };
 }])
 .directive('myDialog', function() {
  return {
   restrict: 'E',
   transclude: true,
   scope: {
    'close': '&onClose'
   },
   templateUrl: 'my-dialog-close.html'
  };
 });
登录后复制

my-dialog-close.html

<div class="alert">
 <a href class="close" ng-click="close()">&times;</a>
 <div ng-transclude></div>
</div>
登录后复制

index.html

<div ng-controller="Controller">
 <my-dialog ng-hide="dialogIsHidden" on-close="hideDialog()">
  Check out the contents, {{name}}!
 </my-dialog>
</div>
登录后复制

如果指令使用了transclude参数,那么在控制器无法正常监听数据模型的变化了。建议在链接函数里使用$watch服务。

9、controller[string or function]

controller参数可以是一个字符串或一个函数。当设置为字符串时,会以字符串的值为名字,来查找注册在应用中的控制器的构造函数.

angular.module('myApp', []) 
.directive('myDirective', function() { 
restrict: 'A', 
controller: 'SomeController' 
}) 
登录后复制

可以在指令内部通过匿名构造函数的方式来定义一个内联的控制器

angular.module('myApp',[]) 
.directive('myDirective', function() { 
restrict: 'A', 
controller: 
function($scope, $element, $attrs, $transclude) { 
// 控制器逻辑放在这里
} 
}); 
登录后复制

我们可以将任意可以被注入的ng服务注入到控制器中,便可以在指令中使用它了。控制器中也有一些特殊的服务可以被注入到指令当中。这些服务有:

1. $scope

与指令元素相关联的当前作用域。
2. $element
当前指令对应的元素。
3. $attrs
由当前元素的属性组成的对象。

<div id="aDiv"class="box"></div>
具有如下的属性对象:
{ 
id: "aDiv", 
class: "box" 
} 
登录后复制

4. $transclude
嵌入链接函数会与对应的嵌入作用域进行预绑定。transclude链接函数是实际被执行用来克隆元素和操作DOM的函数。

 angular.module('myApp',[])
 .directive('myLink', function () {
   return {
     restrict: 'EA',
     transclude: true,
     controller:
     function ($scope, $element,$attrs,$transclude) {
       $transclude(function (clone) {       
         var a = angular.element('<a>');
         a.attr('href', $attrs.value);
         a.text(clone.text());
         $element.append(a);
       });
     }
   };
 });
登录后复制

html

<my-link value="http://www.baidu.com">百度</my-link>
<div my-link value="http://www.google.com">谷歌</div>
登录后复制

仅在compile参数中使用transcludeFn是推荐的做法。link函数可以将指令互相隔离开来,而controller则定义可复用的行为。如果我们希望将当前指令的API暴露给其他指令使用,可以使用controller参数,否则可以使用link来构造当前指令元素的功能性(即内部功能)。如果我们使用了scope.$watch()或者想要与DOM元素做实时的交互,使用链接会是更好的选择。使用了嵌入,控制器中的作用域所反映的作用域可能与我们所期望的不一样,这种情况下,$scope对象无法保证可以被正常更新。当想要同当前屏幕上的作用域交互时,可以使用传入到link函数中的scope参数。

10、controllerAs[string]

controllerAs参数用来设置控制器的别名,这样就可以在视图中引用控制器甚至无需注入$scope。

<div ng-controller="MainController as main">
    <input type="text" ng-model="main.name" />
    <span>{{ main.name }}</span>
  </div> 
登录后复制

JsCode:

 angular.module('myApp',[])
  .controller('MainController', function () {
    this.name = "Halower";
  });
登录后复制

控制器的别名使路由和指令具有创建匿名控制器的强大能力。这种能力可以将动态的对象创建成为控制器,并且这个对象是隔离的、易于测试。

11、 require[string or string[]]

require为字符串代表另外一个指令的名字。require会将控制器注入到其所指定的指令中,并作为当前指令的链接函数的第四个参数。字符串或数组元素的值是会在当前指令的作用域中使用的指令名称。在任何情况下,ng编译器在查找子控制器时都会参考当前指令的模板。

如果不使用^前缀,指令只会在自身的元素上查找控制器。指令定义只会查找定义在指令作当前用域中的ng-model=""
如果使用?前缀,在当前指令中没有找到所需要的控制器,会将null作为传给link函数的第四个参数。
如果添加了^前缀,指令会在上游的指令链中查找require参数所指定的控制器。
如果添加了?^ 将前面两个选项的行为组合起来,我们可选择地加载需要的指令并在父指令链中进行查找
如果没有任何前缀,指令将会在自身所提供的控制器中进行查找,如果没有找到任何控制器(或具有指定名字的指令)就抛出一个错误
12、compile【object or function】

compile选项本身并不会被频繁使用,但是link函数则会被经常使用。本质上,当我们设置了link选项,实际上是创建了一个postLink() 链接函数,以便compile() 函数可以定义链接函数。通常情况下,如果设置了compile函数,说明我们希望在指令和实时数据被放到DOM中之前进行DOM操作,在这个函数中进行诸如添加和删除节点等DOM操作是安全的。

compile和link选项是互斥的。如果同时设置了这两个选项,那么会把compile所返回的函数当作链接函数,而link选项本身则会被忽略。

编译函数负责对模板DOM进行转换。链接函数负责将作用域和DOM进行链接。 在作用域同DOM链接之前可以手动操作DOM。在实践中,编写自定义指令时这种操作是非常罕见的,但有几个内置指令提供了这样的功能。

13、link

compile: function(tEle, tAttrs, transcludeFn) {
 //todo:
 return function(scope, ele, attrs) {
 // 链接函数
 };
登录后复制

链接函数是可选的。如果定义了编译函数,它会返回链接函数,因此当两个函数都定义时,编译函数会重载链接函数。如果我们的指令很简单,并且不需要额外的设置,可以从工厂函数(回调函数)返回一个函数来代替对象。如果这样做了,这个函数就是链接函数。

14、ngModel

它提供更底层的API来处理控制器内的数据,这个API用来处理数据绑定、验证、 CSS更新等不实际操作DOM的事情,ngModel 控制器会随 ngModel 被一直注入到指令中,其中包含了一些方法。为了访问ngModelController必须使用require设置.

ngModelController常用的元素如下:

1).为了设置作用域中的视图值,需要调用 ngModel.$setViewValue() 函数。
$setViewValue() 方法适合于在自定义指令中监听自定义事件(比如使用具有回调函数的jQuery插件),我们会希望在回调时设置$viewValue并执行digest循环。

 angular.module('myApp')
    .directive('myDirective', function() {
      return {
        require: '&#63;ngModel',
        link: function(scope, ele, attrs, ngModel) {
          if (!ngModel) return;
          $(function() {
            ele.datepicker({
               //回调函数
              onSelect: function(date) {
                // 设置视图和调用 apply
                scope.$apply(function() {
                  ngModel.$setViewValue(date);
                });
              }
            });
          });
        }
      };
    });
登录后复制

2).$render方法可以定义视图具体的渲染方式
3).属性(这里属性可以参考前一篇文章末尾进行学习)

以上就是关于AngularJs指令的全部内容,希望对大家的学习有所帮助。

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

泰拉瑞亚怎么用指令获得物品?-泰拉瑞亚怎么收藏物品? 泰拉瑞亚怎么用指令获得物品?-泰拉瑞亚怎么收藏物品? Mar 19, 2024 am 08:13 AM

泰拉瑞亚怎么用指令获得物品?一、什么是泰拉瑞亚给予物品指令在泰拉瑞亚游戏中,给予物品指令是一项非常实用的功能。通过这个指令,玩家可以直接获取需要的物品,而不必费力地去打怪或者传送到某个地点。这样可以极大地节省时间,提高游戏的效率,让玩家更专注于探索和建设世界。总的来说,这个功能让游戏体验变得更加流畅和愉快。二、如何使用泰拉瑞亚给予物品指令1.打开游戏并进入游戏界面。2.按下键盘上的“Enter”键,打开聊天窗口。3.在聊天窗口中输入指令的格式:“/give[玩家名称][物品ID][物品数量]”。

VUE3快速入门:使用Vue.js指令实现选项卡切换 VUE3快速入门:使用Vue.js指令实现选项卡切换 Jun 15, 2023 pm 11:45 PM

本文旨在帮助初学者快速入手Vue.js3,实现简单的选项卡切换效果。Vue.js是一个流行的JavaScript框架,可用于构建可重用的组件、轻松管理应用程序的状态和处理用户界面的交互操作。Vue.js3是该框架的最新版本,相较于之前的版本变动较大,但基本原理并未改变。在本文中,我们将使用Vue.js指令实现选项卡切换效果,目的是让读者熟悉Vue.js的

2022年最新5款的angularjs教程从入门到精通 2022年最新5款的angularjs教程从入门到精通 Jun 15, 2017 pm 05:50 PM

Javascript 是一个非常有个性的语言. 无论是从代码的组织, 还是代码的编程范式, 还是面向对象理论都独具一格. 而很早就在争论的Javascript 是不是面向对象语言这个问题, 显然已有答案. 但是, 即使 Javascript 叱咤风云二十年, 如果想要看懂 jQuery, Angularjs, 甚至是 React 等流行框架, 观看《黑马云课堂JavaScript 高级框架设计视频教程》就对了。

探索自带MC指令的输入法的无限可能性(打造完美游戏体验的创新工具——自带MC指令输入法) 探索自带MC指令的输入法的无限可能性(打造完美游戏体验的创新工具——自带MC指令输入法) May 02, 2024 pm 03:01 PM

移动设备成为人们生活中必不可少的一部分,在现代社会。而游戏也成为人们闲暇时的主要娱乐方式之一。不断有人致力于开发新的工具和技术来优化游戏玩法,为了提高游戏体验。而自带MC指令的输入法就是其中一种引人注目的创新。以及它如何为玩家们带来更好的游戏体验,本文将深入探讨自带MC指令输入法的无限可能性。自带MC指令输入法简介自带MC指令输入法是一种结合了MC指令和智能输入法功能的创新工具。从而实现更多的操作和功能,通过在移动设备上安装该输入法、玩家可以方便地在游戏中使用各种指令。快速输入指令,提高游戏效率

使用PHP和AngularJS搭建一个响应式网站,提供优质的用户体验 使用PHP和AngularJS搭建一个响应式网站,提供优质的用户体验 Jun 27, 2023 pm 07:37 PM

在如今信息时代,网站已经成为人们获取信息和交流的重要工具。一个响应式的网站能够适应各种设备,为用户提供优质的体验,成为了现代网站开发的热点。本篇文章将介绍如何使用PHP和AngularJS搭建一个响应式网站,从而提供优质的用户体验。PHP介绍PHP是一种开源的服务器端编程语言,非常适用于Web开发。PHP具有很多优点,如易于学习、跨平台、丰富的工具库、开发效

计算机能直接执行的指令包括哪两个部分 计算机能直接执行的指令包括哪两个部分 Dec 09, 2020 am 09:15 AM

计算机能直接执行的指令包括操作码和操作数两个部分。操作码是指计算机程序中所规定的要执行操作的那一部分指令或字段,其实就是指令序列号,用来告诉CPU需要执行哪一条指令。

指令是控制计算机执行的命令,它由什么和地址码组成 指令是控制计算机执行的命令,它由什么和地址码组成 Jan 11, 2021 am 11:43 AM

指令是控制计算机执行的命令,它由操作码和地址码组成。通常一条指令包括两方面的内容:操作码和操作数(地址码),操作码决定要完成的操作,操作数指参加运算的数据及其所在的单元地址。

阻止冒泡事件的指令有哪些 阻止冒泡事件的指令有哪些 Nov 21, 2023 pm 04:14 PM

阻止冒泡事件的指令有stopPropagation()、cancelBubble属性、event.stopPropagation()、event.cancelBubble属性、event.stopImmediatePropagation()等。详细介绍:1、stopPropagation()是最常用的指令之一,用于停止事件的传播。当事件触发时,调用该方法可以阻止事件继续等等。

See all articles