www.2527.com_澳门新葡8455手机版_新京葡娱乐场网址_
做最好的网站

AngularJS中的指令实施开拓指南

2019-07-12 10:21 来源:未知

命令(Directives)是富有AngularJS应用最注重的一部分。固然AngularJS已经提供了特别丰硕的吩咐,但依然日常需求创建应用特定的下令。那篇教程会为您呈报如何自定义指令,以及介绍如何在实际上项目中应用。在这篇作品的末梢(第四局地),作者会指引你什么选拔Angular指令来创立多少个粗略的记事本应用。

深深学习JavaScript的AngularJS框架中指令的使用办法,angularjs深远

命令(Directives)是具备AngularJS应用最关键的一对。就算AngularJS已经提供了特别丰裕的指令,但要么有时索要成立应用特定的通令。那篇教程会为你陈述如何自定义指令,以及介绍怎么样在实际上项目中利用。在那篇小说的结尾(第二有个别),笔者会辅导你什么样利用Angular指令来创设贰个简短的记事本应用。

概述

三个发令用来引进新的HTML语法。指令是DOM成分上的标识,使成分具备一定的一坐一起。譬如来讲,静态的HTML不驾驭怎样来创设和表现四个日子选用器控件。让HTML能识别那几个语法,我们须要选用指令。指令通过某种格局来制造七个能够帮忙日期采纳的要素。大家会稳中有进地介绍那是怎样兑现的。 假如您写过AngularJS的选取,那么你势必已经选拔过千叮万嘱,不管您有未有察觉到。你确定已经用过粗略的命令,比方ng-mode, ng-repeat, ng-show等。那一个指令都给以DOM成分特定的一颦一笑。例如,ng-repeat 重复特定的要素,ng-show 有标准地出示八个成分。假设您想让三个因素扶助拖拽,你也需求创制二个限令来促成它。指令背后基本的主张不会细小略。它通过对成分绑定事件监听或许改动DOM而使HTML具备真正的交互性。

jQuery视角

想像一下运用jQuery怎么着创建贰个日子选择器。首先,大家在HTML中增多多个一般性的输入框,然后通过jQuery调用 $(element).dataPicker() 来将它转换成三个日子选取器。可是,细心想转手。当一个规划人员复苏检查HTML标志的时候,他/她是或不是及时猜到这一个字段实际上意味着的从头到尾的经过?那只是叁个轻易易行的输入框,恐怕叁个日子选拔器?你需求查阅jQuery代码来规定那么些。而Angular的主意是使用四个命令来扩充HTML。所以,三个日期选拔器的命令能够是下面的款式:

<input type="text" />

要么是那样:

<input type="text" />

这种创设UI创设的议程更是直白和明晰。你可以自便地通过查阅成分就通晓这到底是怎么。

创造自定义指令:

贰个Angular指令能够有以下的各个表现情势: 1. 多少个新的HTML成分(<data-picker></data-picker>) 2. 因素的品质(<input type=”text” data-picker/>) 3. CSS class(<input type=”text” class=”data-picker”/>) 4. 讲解(<!–directive:data-picker –>) 当然,大家能够决定我们的通令在HTML中的表现格局。上面我们来看一下AngularJS中的贰个超人的吩咐的写法。指令注册的秘技与 controller 一样,可是它回到的是一个兼有指令配置属性的简要对象(指令定义对象) 。上边包车型大巴代码是一个大约的 Hello World 指令。

var app = angular.module('myapp', []);

app.directive('helloWorld', function() {
 return {
   restrict: 'AE',
   replace: 'true',
   template: '<h3>Hello World!!</h3>'
 };
});

在上边的代码中,app.directive()方法在模块中注册了一个新的指令。那几个办法的第一个参数是以此命令的名字。第一个参数是贰个回去指令定义对象的函数。假让你的吩咐正视于任何的靶子可能服务,比方$rootScope, $http, 大概$compile,他们能够在这一个小时被注入。那个命令在HTML中以一个成分选择,如下:

<hello-world/>
//OR
<hello:world/>

或然,以三个性质的诀要利用:

<div hello-world></div>
//OR
<div hello:world/>

譬如你想要符合HTML5的业内,你能够在要素前边增多 x- 或许data-的前缀。所以下边的号子也会相配 helloWorld 指令:

<div data-hello-world></div>
//OR
<div x-hello-world></div>

在意: 在万分指令的时候,Angular会在要素可能性质的名字中去除 x- 或然data- 前缀。 然后将 – 或许 : 连接的字符串转变来驼峰(camelCase)表现格局,然后再与登记过的通令打开相称。这是为何,大家在HTML中以 hello-world 的点子使用 helloWorld 指令。其实,那跟HTML对标签和属性不区分轻重缓急写关于。 固然地方的下令仅仅实现了静态文字的显示,然而此间还是有一点点风趣的点值得大家去开采。我们在指令定义进程中央银行使了多个属性来配置指令。大家来所有人家介绍他们的机能。

  • restrict – 这么些本性用来钦命指令在HTML中如何利用(还记得以前说的,指令的两种表示方法呢)。在上头的例子中,大家利用了 ‘AE'。所以那些命令能够被看成新的HTML成分只怕性质来选取。假如要允许指令被当作class来使用,我们将 restrict 设置成 ‘AEC'。
  • template – 那些特性规定了指令被Angular编写翻译和链接(link)后生成的HTML标识。这几个性子值不肯定就算粗略的字符串。template 能够特别复杂,况且常常满含别的的命令,以及表明式({{ }})等。越多的情事下您可能会看到 templateUrl, 实际不是template。所以,理想状态下,你应该将模板放到贰个一定的HTML文件中,然后将 templateUrl 属性指向它。
  • replace – 那几个性情指明生成的HTML内容是还是不是会交替掉定义此命令的HTML成分。在大家的例证中,大家用 <hello-world></hello-world>的诀要接纳大家的指令,何况将 replace 设置成 true。所以,在指令被编写翻译之后,生成的模版内容替换掉了 <hello-world></hello-world>。最后的出口是 <h3>Hello World!!</h3>。假如您将 replace 设置成 false,也正是暗中认可值,那么生成的沙盘会被插入到定义指令的成分中。

展开那一个 plunker,在”Hello World!!”右键检查成分内容,来更形象地驾驭这么些。

Link函数和Scope

指令生成出的模版其实远非太多意义,除非它在一定的scope下编译。暗中认可情况下,指令并不会创建新的子scope。越多的,它应用父scope。也正是说,倘诺指令存在于二个controller下,它就能够选取这么些controller的scope。 怎样运用scope,我们要用到二个称得上 link 的函数。它由指令定义对象中的link属性配置。让大家来改换一下大家的 helloWorld 指令,当用户在二个输入框中输入一种颜色的称呼时,Hello World 文字的背景象自动产生变化。同一时候,当用户在 Hello World 文字上点击时,背景象变回深橙。 相应的HTML标志如下:

<body ng-controller="MainCtrl">
 <input type="text" ng-model="color" placeholder="Enter a color" />
 <hello-world/>
</body>

修改后的 helloWorld 指令如下:

app.directive('helloWorld', function() {
 return {
  restrict: 'AE',
  replace: true,
  template: '<p style="background-color:{{color}}">Hello World',
  link: function(scope, elem, attrs) {
   elem.bind('click', function() {
    elem.css('background-color', 'white');
    scope.$apply(function() {
     scope.color = "white";
    });
   });
   elem.bind('mouseover', function() {
    elem.css('cursor', 'pointer');
   });
  }
 };
});

咱俩注意到指令定义中的 link 函数。 它有多少个参数:

  • scope – 指令的scope。在大家的例子中,指令的scope正是父controller的scope。
  • elem – 指令的jQLite(jQuery的子集)包装DOM成分。假诺您在引进AngularJS此前引进了jQuery,那么那个因素就是jQuery成分,并非jQLite成分。由于这几个成分已经被jQuery/jQLite包装了,所以我们就在进行DOM操作的时候就无需再采用$()来进展打包。
  • attr – 三个带有了命令所在成分的习性的标准的参数对象。比如,你给三个HTML成分加多了一部分性质:,那么能够在 link 函数中经过 attrs.someAttribute 来利用它。

link函数主要用来为DOM成分增添事件监听、监视模型属性别变化化、以及革新DOM。在下面的下令代码片段中,大家增加了八个事件, click,和 mouseover。click 管理函数用来重新恢复设置 <p> 的背景象,而 mouseover 管理函数改变鼠标为 pointer。在模板中有三个表明式 {{color}},当父scope中的 color 发生变化时,它用来退换 Hello World 文字的背景观。 那些 plunker 演示了这么些概念。

compile函数

compile 函数在 link 函数被实行在此以前用来做一些DOM改换。它接受上面包车型大巴参数:

tElement – 指令所在的因素
attrs – 成分上予以的参数的法规列表
要留心的是 compile 函数不能够访谈 scope,何况必须重返三个 link 函数。不过假诺未有设置 compile 函数,你能够平常地配置 link 函数,(有了compile,就不可能用link,link函数由compile重回)。compile函数能够写成如下的款型:

app.directive('test', function() {
 return {
  compile: function(tElem,attrs) {

//do optional DOM transformation here
   return function(scope,elem,attrs) {

//linking function here
   };
  }
 };
});

大多数的图景下,你只供给采纳 link 函数。那是因为半数以上的命令只供给思考注册事件监听、监视模型、以及更新DOM等,这几个都足以在 link 函数中做到。 不过对于像 ng-repeat 之类的授命,供给克隆和再一次 DOM 成分数11回,在 link 函数实施此前由 compile 函数来成功。这就拉动了多个难点,为何大家须要七个分别的函数来完结生成进程,为何不能够只利用三个?要应对好这一个难题,大家供给明白指令在Angular中是何等被编写翻译的!

指令是什么样被编写翻译的

当使用带领运营的时候,Angular初步运用 $compile 服务遍历DOM成分。那么些服务基于注册过的一声令下在标志文本中检索指令。一旦具备的下令都被识别后,Angular实施他们的 compile 方法。如前方所讲的,compile 方法重回贰个 link 函数,被增加到稍后试行的 link 函数列表中。那被称之为编写翻译阶段。要是三个限令须要被克隆很频仍(举个例子ng-repeat),compile函数只在编写翻译阶段被施行贰回,复制这个模板,然而link 函数会针对各类被复制的实例被实施。所以分开管理,让我们在性质上有一定的压实。那也验证了干吗在 compile 函数中不能访谈到scope对象。 在编写翻译阶段之后,就起来了链接(linking)阶段。在那么些阶段,全部收罗的 link 函数将被依次实践。指令创建出来的沙盘会在科学的scope下被深入分析和拍卖,然后回到具有事件响应的真实性的DOM节点。

改变指令的Scope

私下认可景况下,指令获取它父节点的controller的scope。但那并不适用于全体情状。固然将父controller的scope暴光给指令,那么她们得以轻便地修改 scope 的性质。在好几意况下,你的通令希望能够加多一些只限内部使用的特性和章程。假如我们在父的scope中丰硕,会污染父scope。 其实大家还会有二种接纳:

三个子scope – 那些scope原型承继子父scope。
二个割裂的scope – 贰个孤立存在不连续自父scope的scope。
如此的scope可以通过指令定义对象中 scope 属性来布局。下边包车型地铁代码片段是一个例子:

app.directive('helloWorld', function() {
 return {
  scope: true, 
// use a child scope that inherits from parent
  restrict: 'AE',
  replace: 'true',
  template: '<h3>Hello World!!</h3>'
 };
});

地方的代码,让Angular给指令创制贰个一连自父socpe的新的子scope。 另外一个抉择,隔开的scope:

app.directive('helloWorld', function() {
 return {
  scope: {}, 
// use a new isolated scope
  restrict: 'AE',
  replace: 'true',
  template: '<h3>Hello World!!</h3>'
 };
});

本条命令使用了一个切断的scope。隔绝的scope在大家想要创立可选取的吩咐的时候是十分有实惠的。通过动用隔开的scope,大家能够保障我们的下令是自包含的,能够被很轻便的插入到HTML应用中。 它在那之中不能够访问父的scope,所保险了父scope不被污染。 在大家的 helloWorld 指令例子中,假如我们将 scope 设置成 {},那么地点的代码将不会专门的学业。 它会创制三个新的隔开分离的scope,那么相应的表述式 {{color}} 会指向到那些新的scope中,它的值将是 undefined. 使用隔离的scope并不意味着大家一同不能够访谈父scope的天性。

隔绝scope和父scope之间的数量绑定

一般性,隔开指令的scope会带来大多的平价,更加是在您要操作多少个scope模型的时候。但神跡为了使代码能够准确专门的学业,你也须要从指令内部访问父scope的属性。好消息是Angular给了你足足的灵活性让您可知有采取性的经过绑定的办法传入父scope的性质。让我们重温一下我们的 helloWorld 指令,它的背景象会随着用户在输入框中输入的水彩名称而转换。还记伏贴大家对那么些命令使用隔开scope的之后,它不能办事了吧?以往,我们来让它恢复生机平常。

要是我们已经早先化达成app这些变量所指向的Angular模块。那么我们的 helloWorld 指令如下边代码所示:

app.directive('helloWorld', function() {
 return {
  scope: {},
  restrict: 'AE',
  replace: true,
  template: '<p style="background-color:{{color}}">Hello World</p>',
  link: function(scope, elem, attrs) {
   elem.bind('click', function() {
    elem.css('background-color','white');
    scope.$apply(function() {
     scope.color = "white";
    });
   });
   elem.bind('mouseover', function() {
    elem.css('cursor', 'pointer');
   });
  }
 };
});

应用这一个命令的HTML标签如下:

<body ng-controller="MainCtrl">
 <input type="text" ng-model="color" placeholder="Enter a color"/>
 <hello-world/>
</body>

上面的代码以往是不可能做事的。因为大家用了一个隔开分离的scope,指令内部的 {{color}} 表明式被切断在指令内部的scope中(不是父scope)。不过外面包车型大巴输入框成分中的 ng-model 指令是指向父scope中的 color 属性的。所以,我们须求一种办法来绑定隔开分离scope和父scope中的那八个参数。在Angular中,这种数据绑定能够由此为命令所在的HTML成分增多属性和并下令定义对象中布局相应的 scope 属性来兑现。让大家来细究一下创立数量绑定的两种艺术。

选取一:使用 @ 完毕单向文本绑定

在下边包车型地铁下令定义中,大家钦点了隔开scope中的属性 color 绑定到指令所在HTML成分上的参数 colorAttr。在HTML标识中,你能够看出 {{color}}表明式被内定给了 color-attr 参数。当表明式的值发生退换时,color-attr 参数也跟着变动。隔断scope中的 color 属性的值也应和地被改动。

app.directive('helloWorld', function() {
 return {
  scope: {
   color: '@colorAttr'
  },
  ....

// the rest of the configurations
 };
});

更新后的HTML标识代码如下:

<body ng-controller="MainCtrl">
 <input type="text" ng-model="color" placeholder="Enter a color"/>
 <hello-world color-attr="{{color}}"/>
</body>

咱俩称这种艺术为单项绑定,是因为在这种艺术下,你不得不将字符串(使用表明式{{}})传递给参数。当父scope的性质变化时,你的隔开scope模型中的属性值跟着变动。你以至能够在命令内部监督这一个scope属性的变通,而且触发一些职责。可是,反向的传递并不干活。你不可能透过对隔开scope属性的操作来改变父scope的值。

注意点:
当隔开scope属性和指令成分参数的名字同样是,你能够更简明的措施设置scope绑定:

app.directive('helloWorld', function() {
 return {
  scope: {
   color: '@'
  },
  ....

// the rest of the configurations
 };
});

对应选拔指令的HTML代码如下:

<hello-world color="{{color}}"/>

慎选二:使用 = 完结双向绑定

让大家将下令的概念更换成上面包车型客车指南:

app.directive('helloWorld', function() {
 return {
  scope: {
   color: '='
  },
  ....

// the rest of the configurations
 };
});

对应的HTML修改如下:

<body ng-controller="MainCtrl">
 <input type="text" ng-model="color" placeholder="Enter a color"/>
 <hello-world color="color"/>
</body>

与 @ 不一致,这种措施让您可见给属性钦赐一个诚实的scope数据模型,并不是大致的字符串。那样您就足以传递轻巧的字符串、数组、以至复杂的对象给隔开分离scope。同期,还补助双向的绑定。每当父scope属性别变化化时,相对应的隔开scope中的属性也跟着变动,反之亦然。和事先的同样,你也可以监视那个scope属性的变型。

选用三:使用 & 在父scope中推行函数

有的时候从隔绝scope中调用父scope中定义的函数是极其有不能缺少的。为了能够访问外界scope中定义的函数,我们采取&。譬喻我们想要从指令内部调用 sayHello() 方法。下边的代码告诉大家该如何做:

app.directive('sayHello', function() {
 return {
  scope: {
   sayHelloIsolated: '&'
  },
  ....

// the rest of the configurations
 };
});

相应的HTML代码如下:

<body ng-controller="MainCtrl">
 <input type="text" ng-model="color" placeholder="Enter a color"/>
 <say-hello sayHelloIsolated="sayHello()"/>
</body>

以此 Plunker 例子对地方的概念做了很好的笺注。

父scope、子scope以及隔开scope的分别

作为二个Angular的菜鸟,你恐怕会在选拔正确的通令scope的时候感到纳闷。暗中同意景况下,指令不会创立一个新的scope,而是沿用父scope。不过在无数状态下,那并非大家想要的。假诺您的下令重度地应用父scope的性情、以致创办新的属性,会传染父scope。让抱有的指令都采纳同贰个父scope不会是一个好主意,因为任何人都可能改换这些scope中的属性。因而,上面包车型客车这几个原则或者能够支持你为你的下令采纳正确的scope。

1.父scope(scope: false) – 那是默认情状。如若你的一声令下不操作父scoe的本性,你就无需一个新的scope。这种景色下是能够使用父scope的。

2.子scope(scope: true) – 那会为命令创制多个新的scope,並且原型承袭自父scope。假诺您的下令scope中的属性和方法与其余的命令以及父scope都并未有提到的时候,你应有创造三个新scope。在这种方法下,你同一有所父scope中所定义的天性和格局。

3.隔开分离scope(scope:{}) – 那就如三个沙箱!当你创设的授命是自包罗的还要可接纳的,你就须要接纳这种scope。你在指令中会创造比相当多scope属性和艺术,它们仅在命令内部选择,永世不会被表面的世界所理解。若是是那样的话,隔开的scope是越来越好的采用。隔开分离的scope不会持续父scope。

Transclusion(嵌入)

Transclusion是让我们的授命满含自由内容的章程。大家得以延时提取并在不利的scope下编写翻译那几个嵌入的内容,最终将它们放入指令模板中钦点的任务。 尽管您在指令定义中设置 transclude:true,一个新的放到的scope会被创建,它原型承袭子父scope。 假如您想要你的授命使用隔断的scope,然而它所包括的源委能够在父scope中施行,transclusion也能够扶助。

假设我们报了名贰个之类的授命:

app.directive('outputText', function() {
 return {
  transclude: true,
  scope: {},
  template: '<div ng-transclude></div>'
 };
});

它利用如下:

<div output-text>
 <p>Hello {{name}}</p>
</div>

ng-transclude 指明在哪儿放置被平放的从头到尾的经过。在那些例子中DOM内容 <p>Hello {{name}}</p> 被提取和停放到 <div ng-transclude></div> 内部。有三个很珍视的点需求当心的是,表达式{{name}}所对应的品质是在父scope中被定义的,而非子scope。你能够在那么些Plunker例子中做一些实验。倘诺您想要学习越多关于scope的学识,能够翻阅那篇小说。

transclude:'element' 和 transclude:true的区别

一时自个儿大家要放到指令成分本身,而不光是它的剧情。在这种气象下,我们须求动用 transclude:'element'。它和 transclude:true 分歧,它将标记了 ng-transclude 指令的因素一同包括到了命令模板中。使用transclusion,你的link函数会获得一个名叫transclude 的链接函数,这几个函数绑定了科学的指令scope,而且传入了另贰个享有被置于DOM成分拷贝的函数。你能够在那一个transclude 函数中实施比如修改成分拷贝或许将它加多到DOM上等操作。 类似 ng-repeat 那样的一声令下使用这种艺术来重新DOM成分。留心探究一下那些Plunker,它选取这种情势复制了DOM成分,并且改变了第四个实例的背景观。

一律须要留神的是,在行使 transclude:'element'的时候,指令所在的要素会被调换来HTML注释。所以,如若您结合使用 transclude:'element' 和 replace:false,那么指令模板本质上是被增加到了批注的innerHTML中——约等于说其实什么都未曾发生!相反,借使你挑选使用 replace:true,指令模板会交替HTML注释,那么任何就能够假使所愿的劳作。使用 replade:false 和 transclue:'element'临时候也是可行的,比方当您要求再一次DOM成分不过并不想保留第叁个因素实例(它会被转变到注释)的情事下。对那块还可能有狐疑的同桌能够阅读stackoverflow上的这篇研究,介绍的可比清晰。

controller 函数和 require

若是你想要允许任何的一声令下和您的一声令下发出互相时,你要求使用 controller 函数。比方有个别意况下,你要求经过整合五个指令来完结二个UI组件。那么你能够经过如下的措施来给指令增多二个controller 函数。

app.directive('outerDirective', function() {
 return {
  scope: {},
  restrict: 'AE',
  controller: function($scope, $compile, $http) {

// $scope is the appropriate scope for the directive
   this.addChild = function(nestedDirective) { 
// this refers to the controller
    console.log('Got the message from nested directive:'   nestedDirective.message);
   };
  }
 };
});

以此代码为命令增加了贰个称作 outerDirective 的controller。当另三个发令想要交互时,它须要证明它对您的授命 controller 实例的引用(require)。能够透过如下的秘诀达成:

app.directive('innerDirective', function() {
 return {
  scope: {},
  restrict: 'AE',
  require: '^outerDirective',
  link: function(scope, elem, attrs, controllerInstance) {

//the fourth argument is the controller instance you require
   scope.message = "Hi, Parent directive";
   controllerInstance.addChild(scope);
  }
 };
});

对应的HTML代码如下:

<outer-directive>
 <inner-directive></inner-directive>
</outer-directive>

require: ‘^outerDirective' 告诉Angular在要素以及它的父成分中找寻controller。这样被找到的 controller 实例会作为第四个参数被流传到 link 函数中。在我们的事例中,大家将安置的授命的scope发送给父亲指令。如果您想尝试这几个代码的话,请在开启浏览器调控台的图景下开垦那一个Plunker。同期,那篇Angular官方文书档案上的终极部分给了二个相当好的有关指令交互的例证,是不行值得一读的。

 

叁个记事本应用

这一某些,大家利用Angular指令成立二个归纳的记事本应用。大家会选择HTML5的 localStorage 来囤积笔记。最后的成品在此间,你能够先睹为快。
我们会创制三个展现记事本的一声令下。用户能够查阅他/她成立过的笔记记录。当她点击 add new 按键的时候,记事本会步向可编制状态,何况同意创制新的笔记。当点击 back 开关的时候,新的笔记会被机关保存。笔记的保留使用了四个称为 noteFactory 的厂子类,它利用了 localStorage。工厂类中的代码是特别直白和可领略的。所以我们就集中研讨指令的代码。

第一步

大家从登记 notepad 指令初始。

app.directive('notepad', function(notesFactory) {
 return {
  restrict: 'AE',
  scope: {},
  link: function(scope, elem, attrs) {
  },
  templateUrl: 'templateurl.html'
 };
});

这里有几点供给留意的:

因为大家想让指令可选择,所以选用采用隔开的scope。这些命令能够具有众多与外部未有关联的习性和措施。
以此命令可以以属性恐怕成分的情势被应用,那些被定义在 restrict 属性中。
明天的link函数是空的
本条命令从 templateurl.html 中获得指令模板
第二步

上面包车型地铁HTML组成了命令的模板。

<div class="note-area" ng-show="!editMode">
 <ul>
  <li ng-repeat="note in notes|orderBy:'id'">
   <a href="#" ng-click="openEditor(note.id)">{{note.title}}</a>
  </li>
 </ul>
</div>
<div id="editor" ng-show="editMode" class="note-area" contenteditable="true" ng-bind="noteText"></div>
<a href="#" ng-click="save()" ng-show="editMode">Back</a>
<a href="#" ng-click="openEditor()" ng-show="!editMode">Add Note</a>

多少个主要的注意点:

note 对象中封装了 title,id 和 content。
ng-repeat 用来遍历 notes 中享有的笔记,何况依照自动生成的 id 属性举办升序排序。
咱俩采纳贰个叫 editMode 的习性来指明大家今后在哪一类情势下。在编辑方式下,那特性子的值为 true 並且可编写制定的 div 节点会展现。用户在此处输入本人的笔记。
借使 editMode 为 false,大家就在查看方式,显示全体的 notes。
三个开关也是依赖 editMode 的值而展现和潜伏。
ng-click 指令用来响应开关的点击事件。这么些主意将和 editMode 一齐加多到scope中。
可编写制定的 div 框与 noteText 相绑定,寄放了用户输入的公文。假若您想编辑三个已存在的笔记,那么这一个模型会用它的文件内容起首化那些div 框。
第三步

我们在scope中创设五个誉为 restore() 的新函数,它用来先导化大家应用中的种种调节器。 它会在 link 函数实施的时候被调用,也会在 save 按键被点击的时候调用。

scope.restore = function() {
 scope.editMode = false;
 scope.index = -1;
 scope.noteText = '';
};

作者们在 link 函数的里边创制这几个函数。 editMode 和 noteText 在此以前已经表达过了。 index 用来追踪当前正在编辑的笔记。 当大家在开立八个新的笔记的时候,index 的值会设成 -1. 我们在编写制定一个已存在的笔记的时候,它含有了要命 note 对象的 id 值。

第四步

今天大家要创设四个scope函数来拍卖编辑和保存操作。

scope.openEditor = function(index) {
 scope.editMode = true;

 if (index !== undefined) {
  scope.noteText = notesFactory.get(index).content;
  scope.index = index;
 } else {
  scope.noteText = undefined;
 }
};

scope.save = function() {
 if (scope.noteText !== '') {
  var note = {};

  note.title = scope.noteText.length > 10 ? scope.noteText.substring(0, 10)   '. . .' : scope.noteText;
  note.content = scope.noteText;
  note.id = scope.index != -1 ? scope.index : localStorage.length;
  scope.notes = notesFactory.put(note);
 }

 scope.restore();
};

那五个函数有几点需求专注:

openEditor 为编辑器做希图干活。尽管大家在编排多个笔记,它会赢稳当前笔记的从头到尾的经过还要经过行使 ng-bind 将内容更新到可编写制定的 div 中。
若是大家在成立贰个新的笔记,大家会将 noteText 设置成 undefined,以便当我们在保留笔记的时候,触发相应的监听器。
若果 index 参数是 undefined,它标识用户正在创设二个新的笔记。
save 函数通过运用 notesFactory 来积累笔记。在保存实现后,它会刷新 notes 数组,进而监听器能够监测到笔记列表的变通,来及时更新。
save 函数调用在重新恢复设置 controllers 之后调用restore(),进而得以从编辑格局进入查看形式。
第五步

在 link 函数实践时,大家初叶化 notes 数组,何况为可编制的 div 框绑定三个keydown 事件,进而确认保障我们的 nodeText 模型与 div 中的内容保持同步。大家利用那些 noteText 来保存我们的笔记内容。

var editor = elem.find('#editor');

scope.restore(); 
// initialize our app controls
scope.notes = notesFactory.getAll(); 
// load notes

editor.bind('keyup keydown', function() {
 scope.noteText = editor.text().trim();
});

第六步

末段,大家在HTML就像使用其余的HTML成分一样采用大家的下令,然后开首做速记吧。

<h1 class="title">The Note Making App</h1>
<notepad/>

总结

一个很要紧的点供给专注的是,任何利用jQuery能做的作业,我们都能用Angular指令来成功,而且动用更加少的代码。所以,在应用jQuery在此以前,请思量一下大家能或无法在不举办DOM操作的动静下以越来越好的情势来成功义务。试着使用Angular来十分的小化jQuery的施用呢。
再来看一下大家的记录簿应用,删除笔记的作用被故意漏掉了。鼓励读者们融洽尝试和完成这些意义。 你能够从GitHub上下到这些Demo的源代码。

AngularJS中的指令实施开拓指南(二),angularjs指南

在AngularJS中的指令施行指南(一)中给大家介绍了,怎么样隔断三个发令的scope。第一盘部将承载上一篇一而再介绍。首先,大家拜望到在利用隔开scope的情形下,如何从指令内部访谈到父scope的习性。接着,大家会基于对 controller 函数和 transclusions 研讨怎样为命令选择正确的scope。那篇小说的终极会以通过四个完完全全的记事本应用来实践指令的选用。

隔开分离scope和父scope之间的数码绑定

普普通通,隔断指令的scope会带来非常多的造福,尤其是在你要操作五个scope模型的时候。但不经常为了使代码能够精确工作,你也急需从指令内部访谈父scope的性质。好音信是Angular给了您丰裕的八面后珑令你可以有选择性的经过绑定的法子传入父scope的本性。让大家重申一下大家的 helloWorld 指令,它的背景象会趁着用户在输入框中输入的颜色名称而变化。还记妥当大家对那么些命令使用隔开scope的今后,它不可能做事了吧?以后,大家来让它恢复生机平常。

借使大家已经初阶化完成app那个变量所指向的Angular模块。那么大家的 helloWorld 指令如下边代码所示:

app.directive('helloWorld', function() {
return {
scope: {},
restrict: 'AE',
replace: true,
template: '<p style="background-color:{{color}}">Hello World</p>',
link: function(scope, elem, attrs) {
elem.bind('click', function() {
elem.css('background-color','white');
scope.$apply(function() {
scope.color = "white";
});
});
elem.bind('mouseover', function() {
elem.css('cursor', 'pointer');
});
}
};
});

使用那些命令的HTML标签如下:

<body ng-controller="MainCtrl">
<input type="text" ng-model="color" placeholder="Enter a color"/>
<hello-world/>
</body>

上边的代码今后是不能专门的职业的。因为大家用了一个隔离的scope,指令内部的 {{color}} 表明式被隔绝在指令内部的scope中(不是父scope)。不过外面包车型地铁输入框成分中的 ng-model 指令是指向父scope中的 color 属性的。所以,大家必要一种办法来绑定隔绝scope和父scope中的那多少个参数。在Angular中,这种数据绑定能够因此为命令所在的HTML元素加多属性和并下令定义对象中配备相应的 scope 属性来促成。让大家来细究一下赤贫如洗数量绑定的二种艺术。

挑选一:使用 @ 达成单向文本绑定

在下边包车型的士指令定义中,大家钦点了隔绝scope中的属性 color 绑定到指令所在HTML成分上的参数 colorAttr。在HTML标识中,你可以看来 {{color}}表明式被钦定给了 color-attr 参数。当表明式的值发生更换时,color-attr 参数也随即变动。隔开scope中的 color 属性的值也相应地被改换。

app.directive('helloWorld', function() {
return {
scope: {
color: '@colorAttr'
},
....
// the rest of the configurations
};
});

更新后的HTML标志代码如下:

<body ng-controller="MainCtrl">
<input type="text" ng-model="color" placeholder="Enter a color"/>
<hello-world color-attr="{{color}}"/>
</body>

咱俩称这种方法为单项绑定,是因为在这种办法下,你只可以将字符串(使用表达式{{}})传递给参数。当父scope的属性别变化化时,你的隔绝scope模型中的属性值跟着变动。你以致足以在指令内部监督这一个scope属性的变化,并且触发一些职分。然则,反向的传递并不做事。你不能够透过对隔断scope属性的操作来改动父scope的值。

注意点:

当隔断scope属性和指令成分参数的名字同样是,你能够更简明的章程设置scope绑定:

app.directive('helloWorld', function() {
return {
scope: {
color: '@'
},
....
// the rest of the configurations
};
});

对应采用指令的HTML代码如下:

<hello-world color="{{color}}"/>

分选二:使用 = 达成双向绑定

让大家将下令的定义改动成上边包车型地铁规范:

app.directive('helloWorld', function() {
return {
scope: {
color: '='
},
....
// the rest of the configurations
};
});

对应的HTML修改如下:

<body ng-controller="MainCtrl">
<input type="text" ng-model="color" placeholder="Enter a color"/>
<hello-world color="color"/>
</body>

与 @ 区别,这种方法让您可见给属性钦命贰个一步一个脚踏过的痕迹的scope数据模型,并不是简轻巧单的字符串。那样您就足以传递轻易的字符串、数组、乃至复杂的对象给隔绝scope。同有的时候候,还扶助双向的绑定。每当父scope属性变化时,相呼应的隔开分离scope中的属性也随即变动,反之亦然。和后边的同样,你也得以监视那么些scope属性的更换。

采纳三:使用 & 在父scope中推行函数

不常从隔绝scope中调用父scope中定义的函数是特别有须要的。为了能够访谈外界scope中定义的函数,大家运用 &。比方大家想要从指令内部调用 sayHello() 方法。下边包车型大巴代码告诉大家该怎么做:

app.directive('sayHello', function() {
return {
scope: {
sayHelloIsolated: '&'
},
....
// the rest of the configurations
};
});

对应的HTML代码如下:

<body ng-controller="MainCtrl">
<input type="text" ng-model="color" placeholder="Enter a color"/>
<say-hello sayHelloIsolated="sayHello()"/>
</body>

这一个 Plunker 例子对上面包车型地铁定义做了很好的讲解。

父scope、子scope以及隔开scope的界别

作为叁个Angular的菜鸟,你大概会在选拔准确的命令scope的时候以为困惑。暗中认可情形下,指令不会成立一个新的scope,而是沿用父scope。不过在广大意况下,这并非我们想要的。假使您的吩咐重度地采纳父scope的天性、以至创办新的属性,会传染父scope。让抱有的下令都选取同叁个父scope不会是一个好主意,因为任何人都恐怕修改那个scope中的属性。因此,上面包车型大巴那么些准绳恐怕能够援助你为你的授命选取精确的scope。

1.父scope(scope: false) – 那是暗许情况。如若你的授命不操作父scoe的习性,你就无需一个新的scope。这种意况下是能够利用父scope的。

2.子scope(scope: true) – 那会为命令创设一个新的scope,并且原型承继自父scope。假如您的一声令下scope中的属性和章程与其余的下令以及父scope都未曾关联的时候,你应该成立二个新scope。在这种措施下,你同一享有父scope中所定义的属性和方式。

3.隔开分离scope(scope:{}) – 这就好像叁个沙箱!当您创立的授命是自包括的同期可采用的,你就须求选用这种scope。你在指令中会创立比相当多scope属性和艺术,它们仅在命令内部使用,永恒不会被外表的社会风气所通晓。假使是那样的话,隔断的scope是更加好的挑三拣四。隔绝的scope不会持续父scope。

Transclusion(嵌入)

Transclusion是让大家的通令满含自由内容的点子。大家得以延时提取并在科学的scope下编写翻译那些嵌入的原委,最后将它们放入指令模板中钦定的岗位。 即使你在命令定义中装置 transclude:true,一个新的停放的scope会被创立,它原型继承子父scope。 固然你想要你的通令使用隔绝的scope,可是它所蕴藏的剧情约财富够在父scope中推行,transclusion也得以支持。

若果大家报了名二个之类的指令:

app.directive('outputText', function() {
return {
transclude: true,
scope: {},
template: '<div ng-transclude></div>'
};
});

它选用如下:

<div output-text>
<p>Hello {{name}}</p>
</div>

ng-transclude 指明在哪个地方放置被放到的内容。在这一个例子中DOM内容 <p>Hello {{name}}</p> 被提取和停放到 <div ng-transclude></div> 内部。有二个很首要的点供给注意的是,表达式{{name}}所对应的习性是在父scope中被定义的,而非子scope。你能够在这几个Plunker例子中做一些试行。假如您想要学习越多关于scope的知识,能够翻阅这篇小说。

transclude:'element' 和 transclude:true的区别

有的时候自身大家要放权指令成分本人,而不止是它的原委。在这种情景下,大家必要运用 transclude:'element'。它和 transclude:true 不一样,它将标识了 ng-transclude 指令的要素一齐包括到了命令模板中。使用transclusion,你的link函数会拿走二个誉为 transclude 的链接函数,这几个函数绑定了正确的下令scope,並且传入了另叁个怀有被放置DOM成分拷贝的函数。你能够在那么些transclude 函数中实施举例修改成分拷贝只怕将它增添到DOM上等操作。 类似 ng-repeat 那样的授命使用这种方法来重新DOM成分。细心斟酌一下那个Plunker,它应用这种办法复制了DOM成分,而且改换了第四个实例的背景观。

一样必要专注的是,在选拔transclude:'element'的时候,指令所在的成分会被调换来HTML注释。所以,假诺您结合使用 transclude:'element' 和 replace:false,那么指令模板本质上是被增多到了讲解的innerHTML中——也正是说其实什么都尚未生出!相反,如果你挑选使用 replace:true,指令模板会交替HTML注释,那么一切就能够假设所愿的行事。使用 replade:false 和 transclue:'element'有的时候候也是卓有成效的,比方当您必要重新DOM成分然而并不想保留第三个成分实例(它会被调换来注释)的情形下。对那块还会有疑忌的同班能够阅读stackoverflow上的那篇钻探,介绍的可比明晰。

controller 函数和 require

借使您想要允许任何的授命和您的授命发出互相时,你必要动用 controller 函数。举例有个别景况下,你必要经过结合几个指令来贯彻一个UI组件。那么您能够因而如下的点子来给指令增多叁个controller 函数。

app.directive('outerDirective', function() {
return {
scope: {},
restrict: 'AE',
controller: function($scope, $compile, $http) {
// $scope is the appropriate scope for the directive
this.addChild = function(nestedDirective) { 
// this refers to the controller
console.log('Got the message from nested directive:'   nestedDirective.message);
};
}
};
});

其一代码为命令加多了一个称为 outerDirective 的controller。当另二个下令想要交互时,它必要申明它对您的指令 controller 实例的援引(require)。能够通过如下的法子贯彻:

app.directive('innerDirective', function() {
return {
scope: {},
restrict: 'AE',
require: '^outerDirective',
link: function(scope, elem, attrs, controllerInstance) {

//the fourth argument is the controller instance you require
scope.message = "Hi, Parent directive";
controllerInstance.addChild(scope);
}
};
});

对应的HTML代码如下:

<outer-directive>
<inner-directive></inner-directive>
</outer-directive>

require: ‘^outerDirective' 告诉Angular在要素以及它的父成分中搜索controller。这样被找到的 controller 实例会作为第多个参数被盛传到 link 函数中。在大家的例证中,我们将嵌入的指令的scope发送给老爹指令。要是你想尝尝那个代码的话,请在拉开浏览器调节台的景观下展开这几个Plunker。同一时间,那篇Angular官方文书档案上的最后有的给了一个丰盛好的关于指令交互的例子,是极度值得一读的。

二个记事本应用

这一局地,咱们应用Angular指令创制一个轻便易行的记事本应用。我们会使用HTML5的 localStorage 来存款和储蓄笔记。最后的出品在那边,你能够先睹为快。
大家会创立几人作品表现记事本的授命。用户能够查看他/她开创过的笔记记录。当她点击 add new 按键的时候,记事本会踏向可编制状态,并且同意创制新的笔记。当点击 back 开关的时候,新的笔记会被电动保存。笔记的保留使用了二个叫作 noteFactory 的工厂类,它选择了 localStorage。工厂类中的代码是丰硕直白和可见道的。所以大家就聚焦研讨指令的代码。

第一步

大家从注册 notepad 指令初阶。

app.directive('notepad', function(notesFactory) {
return {
restrict: 'AE',
scope: {},
link: function(scope, elem, attrs) {
},
templateUrl: 'templateurl.html'
};
});

此间有几点必要专注的:

因为大家想让指令可选取,所以接纳接纳隔断的scope。这些命令能够具备相当多与外边未有提到的质量和办法。
那个命令能够以属性恐怕元素的措施被接纳,那几个被定义在 restrict 属性中。
前几日的link函数是空的那一个命令从 templateurl.html 中收获指令模板

第二步

上面包车型客车HTML组成了命令的模板。

<div class="note-area" ng-show="!editMode">
<ul>
<li ng-repeat="note in notes|orderBy:'id'">
<a href="#" ng-click="openEditor(note.id)">{{note.title}}</a>
</li>
</ul>
</div>
<div id="editor" ng-show="editMode" class="note-area" contenteditable="true" ng-bind="noteText"></div>
<a href="#" ng-click="save()" ng-show="editMode">Back</a>
<a href="#" ng-click="openEditor()" ng-show="!editMode">Add Note</a>

多少个第一的注意点:

note 对象中封装了 title,id 和 content。

ng-repeat 用来遍历 notes 中全体的笔记,并且依据自动生成的 id 属性举办升序排序。
大家应用二个叫 editMode 的属性来指明我们明日在哪一类方式下。在编写制定情势下,那性情格的值为 true 况且可编写制定的 div 节点会展现。用户在那边输入自身的笔记。

假诺 editMode 为 false,大家就在翻看格局,显示全体的 notes。

七个按键也是基于 editMode 的值而彰显和隐形。
ng-click 指令用来响应按键的点击事件。这么些方法将和 editMode 一同增添到scope中。
可编写制定的 div 框与 noteText 相绑定,存放了用户输入的文件。借使您想编辑八个已存在的笔记,那么那几个模型会用它的文本内容开始化这个div 框。

第三步

咱俩在scope中创建三个称作 restore() 的新函数,它用来开头化大家运用中的各样调整器。 它会在 link 函数推行的时候被调用,也会在 save 按键被点击的时候调用。

scope.restore = function() {
scope.editMode = false;
scope.index = -1;
scope.noteText = '';
};

咱俩在 link 函数的当中创制这些函数。 editMode 和 noteText 在此之前曾经表达过了。 index 用来追踪当前正在编写的笔记。 当大家在创设贰个新的笔记的时候,index 的值会设成 -1. 我们在编辑一个已存在的笔记的时候,它包罗了老大 note 对象的 id 值。

第四步

当今大家要开创八个scope函数来管理编辑和封存操作。

scope.openEditor = function(index) {
scope.editMode = true;
if (index !== undefined) {
scope.noteText = notesFactory.get(index).content;
scope.index = index;
} else {
scope.noteText = undefined;
}
};
scope.save = function() {
if (scope.noteText !== '') {
var note = {};

note.title = scope.noteText.length > 10 ? scope.noteText.substring(0, 10)   '. . .' : scope.noteText;
note.content = scope.noteText;
note.id = scope.index != -1 ? scope.index : localStorage.length;
scope.notes = notesFactory.put(note);
}
scope.restore();
};

那多少个函数有几点需求注意:

openEditor 为编辑器做希图职业。假若大家在编写三个笔记,它会获得当前笔记的内容还要通过利用 ng-bind 将内容更新到可编写制定的 div 中。

倘诺大家在开创一个新的笔记,大家会将 noteText 设置成 undefined,以便当大家在保留笔记的时候,触发相应的监听器。
假定 index 参数是 undefined,它标识用户正在开创贰个新的笔记。
save 函数通过利用 notesFactory 来囤积笔记。在保存实现后,它会刷新 notes 数组,进而监听器能够监测到笔记列表的变化,来立即更新。
save 函数调用在重新载入参数 controllers 之后调用restore(),进而得以从编辑方式步向查看格局。

第五步

在 link 函数施行时,大家初始化 notes 数组,况且为可编写制定的 div 框绑定三个keydown 事件,进而确定保证大家的 nodeText 模型与 div 中的内容保持同步。大家使用那个 noteText 来保存咱们的笔记内容。

var editor = elem.find('#editor');
scope.restore(); 
// initialize our app controls
scope.notes = notesFactory.getAll(); 
// load notes
editor.bind('keyup keydown', function() {
scope.noteText = editor.text().trim();
});

第六步

终极,我们在HTML就像是使用其余的HTML元素同样使用大家的吩咐,然后初始做速记吧。

<h1 class="title">The Note Making App</h1>
<notepad/>

总结

一个很注重的点须求注意的是,任何利用jQuery能做的事体,大家都能用Angular指令来产生,何况利用越来越少的代码。所以,在选用jQuery在此以前,请考虑一下大家能或不能够在不实行DOM操作的情景下以更加好的章程来产生职责。试着使用Angular来十分小化jQuery的利用呢。

再来看一下大家的记录簿应用,删除笔记的效力被故意漏掉了。鼓励读者们团结尝试和兑现那些作用。 你能够从GitHub上下到这么些德姆o的源代码。

概述

您只怕感兴趣的稿子:

  • 详解JavaScript的AngularJS框架中的表明式与指令
  • 自定义Angular指令与jQuery完结的Bootstrap风格数据双向绑定的单选与多选下拉框
  • 理解AngularJs指令
  • 深切讲授AngularJS中的自定义指令的行使
  • 3个能够立异用户体验的AngularJS指令介绍
  • 详解AngularJS中自定义指令的采用
  • AngularJS学习笔记之ng-options指令
  • AngularJS基础学习笔记之指令
  • AngularJS内置指令
  • Angular用来支配成分的展现与否的原生指令介绍
  • angularjs指令中的compile与link函数详解

指令(Directives)是怀有AngularJS应用最要紧的有的。就算AngularJS已经提供了非...

你恐怕感兴趣的篇章:

  • AngularJS学习笔记之ng-options指令
  • AngularJS学习笔记之宗旨指令(init、repeat)
  • AngularJS内置指令
  • Angularjs编写KindEditor,UEidtor,jQuery指令
  • ANGULALacrosseJS中用NG-BIND指令落成单向绑定的事例
  • angularjs指令中的compile与link函数详解

在AngularJS中的指令实行指南(一)中给大家介绍了,怎么着隔开三个指令的scope。第二有的将...

叁个命令用来引进新的HTML语法。指令是DOM成分上的标志,使成分具备一定的行事。比方来讲,静态的HTML不精晓怎么来制造和表现三个日期选拔器控件。让HTML能分辨这么些语法,大家须求使用指令。指令通过某种格局来创制多个能力所能达到协理日期接纳的成分。大家会稳中有进地介绍那是怎么样达成的。 尽管你写过AngularJS的施用,那么你料定已经采纳过三申五令,不管您有未有觉察到。你一定已经用过简短的授命,举个例子ng-mode, ng-repeat, ng-show等。这么些指令都给予DOM元素特定的行事。比方,ng-repeat 重复特定的因素,ng-show 有法规地体现二个要素。假诺你想让贰个成分帮衬拖拽,你也急需创建一个限令来促成它。指令背后基本的主张很简短。它经过对成分绑定事件监听或许转移DOM而使HTML具备真正的交互性。

jQuery视角

设想一下选取jQuery怎么样创建多个日期选用器。首先,我们在HTML中加多二个平常的输入框,然后通过jQuery调用 $(element).dataPicker() 来将它调换成三个日期选取器。但是,细心想转手。当八个企划职员过来检查HTML标识的时候,他/她是或不是及时猜到这几个字段实际上意味着的原委?那只是三个简易的输入框,大概七个日期接纳器?你须要查阅jQuery代码来规定这几个。而Angular的艺术是使用二个指令来扩展HTML。所以,三个日期选用器的指令能够是底下的样式:

<input type="text" />

照旧是如此:

<input type="text" />

这种成立UI创建的方式更为直白和清楚。你能够恣心所欲地经过翻看成分就知道那到底是什么样。

创办自定义指令:

一个Angular指令能够有以下的各个表现方式: 1. 二个新的HTML成分(<data-picker></data-picker>) 2. 成分的性质(<input type=”text” data-picker/>) 3. CSS class(<input type=”text” class=”data-picker”/>) 4. 讲明(<!–directive:data-picker –>) 当然,大家能够操纵大家的授命在HTML中的表现方式。上面大家来看一下AngularJS中的二个优异的吩咐的写法。指令注册的方式与 controller 同样,可是它回到的是多个具有指令配置属性的简短对象(指令定义对象) 。上边包车型地铁代码是一个简便的 Hello World 指令。

var app = angular.module('myapp', []);

app.directive('helloWorld', function() {
 return {
   restrict: 'AE',
   replace: 'true',
   template: '<h3>Hello World!!</h3>'
 };
});

在上头的代码中,app.directive()方法在模块中登记了四个新的通令。那一个办法的首先个参数是其一命令的名字。第一个参数是三个回到指令定义对象的函数。固然您的一声令下信赖于别的的目的可能服务,譬如$rootScope, $http, 或然$compile,他们得以在那个小时被注入。这么些命令在HTML中以多个因素选拔,如下:

<hello-world/>
//OR
<hello:world/>

抑或,以多本性情的格局采取:

<div hello-world></div>
//OR
<div hello:world/>

假如您想要符合HTML5的标准,你能够在要素前边加多 x- 也许data-的前缀。所以上面的标记也会匹配 helloWorld 指令:

<div data-hello-world></div>
//OR
<div x-hello-world></div>

留心: 在同盟指令的时候,Angular会在要素或许性质的名字中删去 x- 或然data- 前缀。 然后将 – 或许 : 连接的字符串调换到驼峰(camelCase)表现格局,然后再与注册过的吩咐进行相称。那是干吗,大家在HTML中以 hello-world 的艺术利用 helloWorld 指令。其实,那跟HTML对标签和总体性不区分轻重缓急写关于。 固然地方的命令仅仅达成了静态文字的彰显,可是此地依旧有一部分风趣的点值得大家去开采。大家在命令定义进程中动用了四个属性来布置指令。大家来家家户户介绍他们的效能。

  • restrict – 那脾性情用来钦命指令在HTML中如何接纳(还记得在此之前说的,指令的多样表示方法吧)。在上边的事例中,大家应用了 ‘AE'。所以那一个命令能够被看作新的HTML成分或然性质来利用。假若要允许指令被当作class来利用,大家将 restrict 设置成 ‘AEC'。
  • template – 这么些天性规定了命令被Angular编译和链接(link)后生成的HTML标志。那一个性格值不自然假使粗略的字符串。template 能够极度复杂,何况日常包蕴别的的通令,以及表明式({{ }})等。越多的事态下你或然会看到 templateUrl, 并非template。所以,理想状态下,你应该将模板放到叁个一定的HTML文件中,然后将 templateUrl 属性指向它。
  • replace – 这一个天性指明生成的HTML内容是不是会交替掉定义此命令的HTML成分。在大家的例证中,大家用 <hello-world></hello-world>的法子利用大家的吩咐,而且将 replace 设置成 true。所以,在命令被编写翻译之后,生成的模板内容替换掉了 <hello-world></hello-world>。最后的输出是 <h3>Hello World!!</h3>。假若你将 replace 设置成 false,也正是暗中认可值,那么生成的模版会被插入到定义指令的因素中。

开垦那一个 plunker,在”Hello World!!”右键检查成分内容,来更形象地理解那么些。

Link函数和Scope

一声令下生成出的模版其实远非太多意义,除非它在一定的scope下编写翻译。暗许意况下,指令并不会创建新的子scope。更加多的,它选取父scope。也正是说,假诺指令存在于三个controller下,它就能使用那么些controller的scope。 怎样利用scope,我们要用到多少个称呼 link 的函数。它由指令定义对象中的link属性配置。让我们来改换一下大家的 helloWorld 指令,当用户在叁个输入框中输入一种颜色的称谓时,Hello World 文字的背景象自动产生变化。同不时候,当用户在 Hello World 文字上点击时,背景象变回玉绿。 相应的HTML标识如下:

<body ng-controller="MainCtrl">
 <input type="text" ng-model="color" placeholder="Enter a color" />
 <hello-world/>
</body>

修改后的 helloWorld 指令如下:

app.directive('helloWorld', function() {
 return {
  restrict: 'AE',
  replace: true,
  template: '<p style="background-color:{{color}}">Hello World',
  link: function(scope, elem, attrs) {
   elem.bind('click', function() {
    elem.css('background-color', 'white');
    scope.$apply(function() {
     scope.color = "white";
    });
   });
   elem.bind('mouseover', function() {
    elem.css('cursor', 'pointer');
   });
  }
 };
});

大家注意到指令定义中的 link 函数。 它有五个参数:

  • scope – 指令的scope。在大家的例子中,指令的scope正是父controller的scope。
  • elem – 指令的jQLite(jQuery的子集)包装DOM成分。假使您在引进AngularJS在此之前引进了jQuery,那么那么些因素就是jQuery成分,实际不是jQLite成分。由于这几个成分已经被jQuery/jQLite包装了,所以大家就在张开DOM操作的时候就无需再采纳$()来拓展打包。
  • attr – 三个带有了命令所在成分的质量的法则的参数对象。比如,你给二个HTML成分加多了部分属性:,那么能够在 link 函数中通过 attrs.someAttribute 来选拔它。

link函数首要用来为DOM成分加多事件监听、监视模型属性别变化化、以及更新DOM。在下面的指令代码片段中,我们增添了八个事件, click,和 mouseover。click 管理函数用来重新初始化 <p> 的背景观,而 mouseover 管理函数改造鼠标为 pointer。在模板中有五个发挥式 {{color}},当父scope中的 color 爆发变化时,它用来改动 Hello World 文字的背景观。 这一个 plunker 演示了那个概念。

compile函数

compile 函数在 link 函数被施行以前用来做一些DOM改变。它接受下边包车型客车参数:

tElement – 指令所在的成分
attrs – 成分上给以的参数的法规列表
要细心的是 compile 函数无法访谈 scope,並且必须回到一个 link 函数。但是即便未有安装 compile 函数,你能够符合规律地配备 link 函数,(有了compile,就无法用link,link函数由compile重临)。compile函数能够写成如下的样式:

app.directive('test', function() {
 return {
  compile: function(tElem,attrs) {

//do optional DOM transformation here
   return function(scope,elem,attrs) {

//linking function here
   };
  }
 };
});

绝大好多的情形下,你只需求利用 link 函数。那是因为超过半数的命令只要求怀恋注册事件监听、监视模型、以及革新DOM等,这一个都能够在 link 函数中形成。 可是对于像 ng-repeat 之类的授命,必要克隆和重新 DOM 成分多次,在 link 函数实施在此之前由 compile 函数来达成。那就推动了一个主题材料,为何我们必要多少个分别的函数来变成生成进程,为何无法只行使八个?要回答好这一个主题素材,大家要求领会指令在Angular中是怎么被编写翻译的!

一声令下是怎么样被编写翻译的

当使用辅导运维的时候,Angular起首利用 $compile 服务遍历DOM成分。那个服务基于注册过的一声令下在标识文本中搜寻指令。一旦具备的下令都被识别后,Angular施行他们的 compile 方法。如前方所讲的,compile 方法再次来到二个 link 函数,被增加到稍后实施的 link 函数列表中。那被堪称编写翻译阶段。借使八个下令须要被克隆很频仍(比如ng-repeat),compile函数只在编译阶段被试行二遍,复制那么些模板,可是link 函数会针对种种被复制的实例被实践。所以分开管理,让我们在性质上有一定的进步。那也验证了干吗在 compile 函数中无法访问到scope对象。 在编写翻译阶段之后,就初步了链接(linking)阶段。在那一个等第,全体收集的 link 函数将被逐个试行。指令创制出来的模版会在正确的scope下被深入分析和拍卖,然后再次来到具备事件响应的真人真事的DOM节点。

变动指令的Scope

默许情况下,指令获取它父节点的controller的scope。但那并不适用于具备情况。借使将父controller的scope揭示给指令,那么她们得以随意地修改 scope 的习性。在好几情状下,你的通令希望能够增添一些只限内部使用的属性和方法。假使大家在父的scope中丰盛,会污染父scope。 其实我们还应该有三种选拔:

三个子scope – 这些scope原型承袭子父scope。
四个隔开分离的scope – 二个孤立存在不延续自父scope的scope。
那样的scope可以经过指令定义对象中 scope 属性来配置。下边包车型地铁代码片段是贰个事例:

app.directive('helloWorld', function() {
 return {
  scope: true, 
// use a child scope that inherits from parent
  restrict: 'AE',
  replace: 'true',
  template: '<h3>Hello World!!</h3>'
 };
});

上边的代码,让Angular给指令创立三个接续自父socpe的新的子scope。 其它一个摘取,隔开的scope:

app.directive('helloWorld', function() {
 return {
  scope: {}, 
// use a new isolated scope
  restrict: 'AE',
  replace: 'true',
  template: '<h3>Hello World!!</h3>'
 };
});

那一个命令使用了贰个隔绝的scope。隔绝的scope在大家想要成立可选择的一声令下的时候是不行有益处的。通过选择隔开的scope,大家能够保障我们的命令是自包罗的,能够被很轻易的插入到HTML应用中。 它个中无法访谈父的scope,所保障了父scope不被污染。 在大家的 helloWorld 指令例子中,要是大家将 scope 设置成 {},那么地方的代码将不会做事。 它会创设多少个新的隔开的scope,那么相应的抒发式 {{color}} 会指向到这一个新的scope中,它的值将是 undefined. 使用隔开分离的scope并不意味我们一起不可能访谈父scope的质量。

隔断scope和父scope之间的数目绑定

普普通通,隔绝指令的scope会带来很多的方便,非常是在您要操作多个scope模型的时候。但有的时候为了使代码可以准确专门的学问,你也须要从指令内部访谈父scope的性质。好消息是Angular给了你足够的灵活性让您可见有选取性的经过绑定的艺术传入父scope的属性。让我们每每一下大家的 helloWorld 指令,它的背景象会趁着用户在输入框中输入的水彩名称而更动。还记妥善大家对这么些命令使用隔断scope的之后,它不能够工作了吗?今后,大家来让它苏醒符合规律。

假使大家早就起初化完毕app这几个变量所指向的Angular模块。那么大家的 helloWorld 指令如上面代码所示:

app.directive('helloWorld', function() {
 return {
  scope: {},
  restrict: 'AE',
  replace: true,
  template: '<p style="background-color:{{color}}">Hello World</p>',
  link: function(scope, elem, attrs) {
   elem.bind('click', function() {
    elem.css('background-color','white');
    scope.$apply(function() {
     scope.color = "white";
    });
   });
   elem.bind('mouseover', function() {
    elem.css('cursor', 'pointer');
   });
  }
 };
});

选取那个命令的HTML标签如下:

<body ng-controller="MainCtrl">
 <input type="text" ng-model="color" placeholder="Enter a color"/>
 <hello-world/>
</body>

上边包车型地铁代码今后是不能够源办公室事的。因为大家用了二个切断的scope,指令内部的 {{color}} 表明式被割裂在命令内部的scope中(不是父scope)。不过外部的输入框成分中的 ng-model 指令是指向父scope中的 color 属性的。所以,大家必要一种情势来绑定隔绝scope和父scope中的那八个参数。在Angular中,这种多少绑定能够经过为命令所在的HTML成分加多属性和并命令定义对象中配备相应的 scope 属性来落到实处。让我们来细究一下四壁萧条数量绑定的几种方法。

挑选一:使用 @ 达成单向文本绑定

在下边包车型大巴命令定义中,大家内定了隔开分离scope中的属性 color 绑定到指令所在HTML成分上的参数 colorAttr。在HTML标识中,你能够看来 {{color}}表达式被钦点给了 color-attr 参数。当表明式的值爆发变动时,color-attr 参数也随即变动。隔断scope中的 color 属性的值也对应地被改造。

app.directive('helloWorld', function() {
 return {
  scope: {
   color: '@colorAttr'
  },
  ....

// the rest of the configurations
 };
});

更新后的HTML标志代码如下:

<body ng-controller="MainCtrl">
 <input type="text" ng-model="color" placeholder="Enter a color"/>
 <hello-world color-attr="{{color}}"/>
</body>

大家称这种办法为单项绑定,是因为在这种办法下,你不得不将字符串(使用表明式{{}})传递给参数。当父scope的属性别变化化时,你的隔断scope模型中的属性值跟着变动。你仍是可以在命令内部监察这几个scope属性的扭转,並且触发一些职务。但是,反向的传递并不办事。你不能通过对隔开scope属性的操作来改变父scope的值。

注意点:
当隔开分离scope属性和指令成分参数的名字同样是,你能够更简便易行的办法设置scope绑定:

app.directive('helloWorld', function() {
 return {
  scope: {
   color: '@'
  },
  ....

// the rest of the configurations
 };
});

相应选取指令的HTML代码如下:

<hello-world color="{{color}}"/>

慎选二:使用 = 达成双向绑定

让大家将指令的概念改换成上面包车型客车理所必然:

app.directive('helloWorld', function() {
 return {
  scope: {
   color: '='
  },
  ....

// the rest of the configurations
 };
});

相应的HTML修改如下:

<body ng-controller="MainCtrl">
 <input type="text" ng-model="color" placeholder="Enter a color"/>
 <hello-world color="color"/>
</body>

与 @ 分化,这种方法令你能够给属性钦命八个诚实的scope数据模型,实际不是简轻便单的字符串。那样您就可以传递轻便的字符串、数组、乃至复杂的目的给隔开分离scope。同有的时候候,还帮忙双向的绑定。每当父scope属性别变化化时,相呼应的隔开scope中的属性也随后变动,反之亦然。和在此以前的一模一样,你也得以监视那几个scope属性的变化。

选用三:使用 & 在父scope中试行函数

有的时候从隔离scope中调用父scope中定义的函数是极其有要求的。为了能够访谈外界scope中定义的函数,大家选拔&。举个例子大家想要从指令内部调用 sayHello() 方法。上面的代码告诉我们该如何做:

app.directive('sayHello', function() {
 return {
  scope: {
   sayHelloIsolated: '&'
  },
  ....

// the rest of the configurations
 };
});

相应的HTML代码如下:

<body ng-controller="MainCtrl">
 <input type="text" ng-model="color" placeholder="Enter a color"/>
 <say-hello sayHelloIsolated="sayHello()"/>
</body>

其一 Plunker 例子对地方的概念做了很好的评释。

父scope、子scope以及隔开scope的区分

作为二个Angular的菜鸟,你恐怕会在甄选正确的一声令下scope的时候感觉困惑。暗中同意情状下,指令不会创制二个新的scope,而是沿用父scope。可是在众多状态下,那实际不是大家想要的。假使您的指令重度地运用父scope的习性、乃至创办新的习性,会污染父scope。让具备的授命都采取同叁个父scope不会是二个好主意,因为任何人都大概改换这些scope中的属性。由此,下边包车型地铁这些标准恐怕能够扶助您为您的命令选择准确的scope。

1.父scope(scope: false) – 那是默许处境。如果你的命令不操作父scoe的质量,你就没有须要三个新的scope。这种境况下是能够利用父scope的。

2.子scope(scope: true) – 那会为命令创制三个新的scope,并且原型承继自父scope。如若您的通令scope中的属性和方法与别的的授命以及父scope都并未有提到的时候,你应当创造二个新scope。在这种方法下,你同样颇具父scope中所定义的习性和措施。

3.隔开分离scope(scope:{}) – 那就如三个沙箱!当您创制的命令是自包涵的同一时候可选择的,你就需求使用这种scope。你在指令中会创制非常多scope属性和办法,它们仅在命令内部使用,恒久不会被外表的社会风气所精通。借使是那样的话,隔绝的scope是更加好的选项。隔断的scope不会持续父scope。

Transclusion(嵌入)

Transclusion是让我们的下令包蕴自由内容的措施。大家得以延时提取并在科学的scope下编写翻译那些嵌入的源委,最后将它们归入指令模板中钦定的地方。 若是您在命令定义中装置 transclude:true,一个新的放权的scope会被创建,它原型承接子父scope。 假令你想要你的一声令下使用隔开的scope,但是它所包蕴的剧情约财富够在父scope中举办,transclusion也足以辅助。

假定大家报了名三个之类的吩咐:

app.directive('outputText', function() {
 return {
  transclude: true,
  scope: {},
  template: '<div ng-transclude></div>'
 };
});

它应用如下:

<div output-text>
 <p>Hello {{name}}</p>
</div>

ng-transclude 指明在哪个地方放置被安置的内容。在这一个例子中DOM内容 <p>Hello {{name}}</p> 被提取和停放到 <div ng-transclude></div> 内部。有三个很要紧的点必要专注的是,表达式{{name}}所对应的属性是在父scope中被定义的,而非子scope。你能够在这一个Plunker例子中做一些尝试。假如你想要学习更加多关于scope的文化,能够翻阅那篇小说。

transclude:'element' 和 transclude:true的区别

奇迹小编我们要放到指令成分自身,而不只是它的剧情。在这种状态下,大家须求选用transclude:'element'。它和 transclude:true 分裂,它将符号了 ng-transclude 指令的要素一齐包括到了指令模板中。使用transclusion,你的link函数会收获一个称呼 transclude 的链接函数,那么些函数绑定了不利的通令scope,并且传入了另二个独具被放到DOM成分拷贝的函数。你能够在那么些transclude 函数中实行比方修改成分拷贝只怕将它增加到DOM上等操作。 类似 ng-repeat 那样的下令使用这种办法来重新DOM元素。留心商量一下那个Plunker,它选择这种艺术复制了DOM成分,并且退换了第三个实例的背景观。

相同要求留意的是,在应用 transclude:'element'的时候,指令所在的要素会被转换到HTML注释。所以,即使您结合使用 transclude:'element' 和 replace:false,那么指令模板本质上是被增添到了批注的innerHTML中——也等于说其实什么都未有发出!相反,如若你挑选选取replace:true,指令模板会交替HTML注释,那么整个就能要是所愿的劳作。使用 replade:false 和 transclue:'element'一时候也是平价的,比如当你要求再度DOM成分不过并不想保留第一个要素实例(它会被转变到注释)的事态下。对那块还也许有狐疑的同校能够翻阅stackoverflow上的那篇钻探,介绍的比较明晰。

controller 函数和 require

倘让你想要允许别的的下令和您的命令发出相互时,你供给选用 controller 函数。比方有些意况下,你需求经过整合多个指令来促成叁个UI组件。那么你能够透过如下的措施来给指令增加贰个controller 函数。

app.directive('outerDirective', function() {
 return {
  scope: {},
  restrict: 'AE',
  controller: function($scope, $compile, $http) {

// $scope is the appropriate scope for the directive
   this.addChild = function(nestedDirective) { 
// this refers to the controller
    console.log('Got the message from nested directive:'   nestedDirective.message);
   };
  }
 };
});

这一个代码为命令增加了三个称为 outerDirective 的controller。当另叁个指令想要交互时,它须要申明它对你的吩咐 controller 实例的援引(require)。能够因而如下的法门完结:

app.directive('innerDirective', function() {
 return {
  scope: {},
  restrict: 'AE',
  require: '^outerDirective',
  link: function(scope, elem, attrs, controllerInstance) {

//the fourth argument is the controller instance you require
   scope.message = "Hi, Parent directive";
   controllerInstance.addChild(scope);
  }
 };
});

对应的HTML代码如下:

<outer-directive>
 <inner-directive></inner-directive>
</outer-directive>

require: ‘^outerDirective' 告诉Angular在要素以及它的父成分中搜索controller。那样被找到的 controller 实例会作为第多个参数被流传到 link 函数中。在我们的例子中,大家将停放的吩咐的scope发送给父亲指令。借使您想尝尝这几个代码的话,请在拉开浏览器调整台的景况下开采这些Plunker。同一时候,那篇Angular官方文书档案上的尾声有的给了三个十三分好的关于指令交互的例子,是那贰个值得一读的。

 

多个记事本应用

这一某些,我们运用Angular指令创立二个差不离的记事本应用。大家会选用HTML5的 localStorage 来积累笔记。最后的产品在此间,你能够先睹为快。
大家会创立三人作品表现记事本的命令。用户能够查看他/她创设过的笔记记录。当她点击 add new 按键的时候,记事本会步向可编写制定状态,并且同意创制新的笔记。当点击 back 按键的时候,新的笔记会被电动保存。笔记的保留使用了八个称为 noteFactory 的工厂类,它利用了 localStorage。工厂类中的代码是相当直白和可驾驭的。所以大家就集中探究指令的代码。

第一步

我们从登记 notepad 指令伊始。

app.directive('notepad', function(notesFactory) {
 return {
  restrict: 'AE',
  scope: {},
  link: function(scope, elem, attrs) {
  },
  templateUrl: 'templateurl.html'
 };
});

那边有几点须求注意的:

因为大家想让指令可选取,所以选择使用隔断的scope。这么些命令可以具备广大与外边未有关系的天性和方法。
其一命令能够以属性可能成分的方法被运用,那么些被定义在 restrict 属性中。
后天的link函数是空的
以此命令从 templateurl.html 中获取指令模板
第二步

上边包车型客车HTML组成了命令的模板。

<div class="note-area" ng-show="!editMode">
 <ul>
  <li ng-repeat="note in notes|orderBy:'id'">
   <a href="#" ng-click="openEditor(note.id)">{{note.title}}</a>
  </li>
 </ul>
</div>
<div id="editor" ng-show="editMode" class="note-area" contenteditable="true" ng-bind="noteText"></div>
<a href="#" ng-click="save()" ng-show="editMode">Back</a>
<a href="#" ng-click="openEditor()" ng-show="!editMode">Add Note</a>

多少个第一的注意点:

note 对象中封装了 title,id 和 content。
ng-repeat 用来遍历 notes 中持有的笔记,並且依据自动生成的 id 属性进行升序排序。
我们使用八个叫 editMode 的属性来指明大家前天在哪类形式下。在编辑情势下,那么些天性的值为 true 而且可编写制定的 div 节点会展现。用户在这里输入本人的笔记。
万一 editMode 为 false,大家就在翻看模式,展现全体的 notes。
多少个开关也是基于 editMode 的值而显得和隐形。
ng-click 指令用来响应按键的点击事件。这个方式将和 editMode 一齐增多到scope中。
可编制的 div 框与 noteText 相绑定,寄存了用户输入的文本。假设你想编辑三个已存在的笔记,那么这么些模型会用它的文件内容开始化那几个div 框。
第三步

大家在scope中创设一个誉为 restore() 的新函数,它用来起先化我们运用中的各个调节器。 它会在 link 函数施行的时候被调用,也会在 save 开关被点击的时候调用。

scope.restore = function() {
 scope.editMode = false;
 scope.index = -1;
 scope.noteText = '';
};

大家在 link 函数的中间成立那些函数。 editMode 和 noteText 在此之前已经表明过了。 index 用来跟踪当前正值编写制定的笔记。 当我们在开立三个新的笔记的时候,index 的值会设成 -1. 大家在编写三个已存在的笔记的时候,它饱含了那些 note 对象的 id 值。

第四步

前天大家要创建四个scope函数来拍卖编辑和保存操作。

scope.openEditor = function(index) {
 scope.editMode = true;

 if (index !== undefined) {
  scope.noteText = notesFactory.get(index).content;
  scope.index = index;
 } else {
  scope.noteText = undefined;
 }
};

scope.save = function() {
 if (scope.noteText !== '') {
  var note = {};

  note.title = scope.noteText.length > 10 ? scope.noteText.substring(0, 10)   '. . .' : scope.noteText;
  note.content = scope.noteText;
  note.id = scope.index != -1 ? scope.index : localStorage.length;
  scope.notes = notesFactory.put(note);
 }

 scope.restore();
};

那五个函数有几点供给小心:

openEditor 为编辑器做希图专门的学问。若是我们在编写制定三个笔记,它会博安妥前笔记的开始和结果还要通过运用 ng-bind 将内容更新到可编写制定的 div 中。
万一我们在开创贰个新的笔记,大家会将 noteText 设置成 undefined,以便当大家在保留笔记的时候,触发相应的监听器。
假设 index 参数是 undefined,它注明用户正在创造多少个新的笔记。
save 函数通过选取 notesFactory 来积攒笔记。在保存实现后,它会刷新 notes 数组,进而监听器能够监测到笔记列表的改造,来立刻更新。
save 函数调用在重新载入参数 controllers 之后调用restore(),进而能够从编辑情势步向查看方式。
第五步

在 link 函数施行时,我们起头化 notes 数组,并且为可编制的 div 框绑定二个keydown 事件,进而保障大家的 nodeText 模型与 div 中的内容保持同步。大家使用那些 noteText 来保存大家的笔记内容。

var editor = elem.find('#editor');

scope.restore(); 
// initialize our app controls
scope.notes = notesFactory.getAll(); 
// load notes

editor.bind('keyup keydown', function() {
 scope.noteText = editor.text().trim();
});

第六步

最后,大家在HTML就像是使用任何的HTML元素一样选用大家的通令,然后起头做笔记吧。

<h1 class="title">The Note Making App</h1>
<notepad/>

总结

二个比较重大的点需求小心的是,任何利用jQuery能做的事情,大家都能用Angular指令来成功,而且利用越来越少的代码。所以,在使用jQuery在此以前,请思虑一下大家能还是不能够在不开始展览DOM操作的处境下以更加好的方法来成功职务。试着使用Angular来极小化jQuery的选取啊。
再来看一下我们的记录簿应用,删除笔记的功用被故意漏掉了。鼓励读者们团结尝试和兑现那么些职能。 你能够从GitHub上下到那些德姆o的源代码。

您可能感兴趣的稿子:

  • AngularJS入门教程之AngularJS指令
  • AngularJS中的指令实施开荒指南(二)
  • AngularJS 中的指令实行开荒指南(一)
  • 浅析AngularJS中的指令
  • 详解JavaScript的AngularJS框架中的说明式与指令
  • 理解AngularJs指令
  • 深远批注AngularJS中的自定义指令的行使
  • 详解AngularJS中自定义指令的利用
  • 整治AngularJS中的一些常用命令
  • AngularJS中的指令全面解析(不可不看)
TAG标签:
版权声明:本文由澳门新葡8455手机版发布于Web前端,转载请注明出处:AngularJS中的指令实施开拓指南