angular 自定义指令详解
<h2>一:指令的创建</h2><p>创建module:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> module1 = angular.module('module1'<span style="color: rgba(0, 0, 0, 1)">,[]);
angular.bootstrap(document.body,[</span>'module1']);</pre>
</div>
<p>创建controller:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> module1 = angular.module('module1'<span style="color: rgba(0, 0, 0, 1)">,[]);
module1.controller(</span>'ctl1', <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">($scope) {
$scope.content </span>= 'i\'m, module 1'<span style="color: rgba(0, 0, 0, 1)">;
$scope.name </span>= 'module1'<span style="color: rgba(0, 0, 0, 1)">;
$scope.save </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
console.log(</span>'is function save'<span style="color: rgba(0, 0, 0, 1)">);
};
});
angular.bootstrap(document.body,[</span>'module1']);</pre>
</div>
<p>创建指令(directive):</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 衔接上面的代码</span>
module1.directive('testDirective', <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 将对象return出去</span>
<span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">{
restrict: </span>'E',<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 指令类型E:element A:attribute M:comment C: class</span>
template: '<div>我是指令生成的内容</div>'<span style="color: rgba(0, 0, 0, 1)">;
replace: </span><span style="color: rgba(0, 0, 255, 1)">true</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">使用模板替换原始标记指令内原本的数据将被清空</span>
<span style="color: rgba(0, 0, 0, 1)"> }
});
angular.bootstrap(document.body,[</span>'module1']);</pre>
</div>
<p>html引入指令:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(255, 0, 0, 1)">ng-controller</span><span style="color: rgba(0, 0, 255, 1)">="ctl1"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)">{{content}}
</span><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">test-directive</span><span style="color: rgba(0, 0, 255, 1)">></span>这是原本的内容<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">test-directive</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<p>以上代码需要注意一下几点:</p>
<p><strong>1.我们定义的指令名称是testDirective,但是在html中要写成test-directive。</strong></p>
<p><strong>2.我们把指令里面的代码都放在了function中的return里面,其实return出去的内容就是整个指令对象。</strong></p>
<p><strong>3.angular.bootstrap(document.body,['module1']);相当于我们在html中使用ng-app指令。推荐使用bootstarp而不是ng-app;</strong></p>
<h2>二、指令的属性</h2>
<p>指令的属性如下:</p>
<ul>
<li>name</li>
<li>priority</li>
<li>terminal</li>
<li>restrict</li>
<li>template</li>
<li>templateUrl</li>
<li>replace</li>
<li>transclude</li>
<li>scope</li>
<li>controller</li>
<li>link</li>
<li>controllerAs</li>
<li>require</li>
<li>compile</li>
</ul>
<p>name:就是指令名,对应上面代码中的testDirective</p>
<hr>
<p> </p>
<p>priority:多个指令设置在同一个元素上的执行优先级,执行顺序从低至高:1>2>3.priority的值为正整数,比如priority: 1</p>
<hr>
<p> </p>
<p>terminal: true/false 如果为true,同一个元素上的其他指令的优先级高于本指令,其他指令将停止执行</p>
<hr>
<p> </p>
<p>restrict:ngular内置的一些指令,比如<strong>ng-app,ng-click</strong>之类的,都是以html元素的<strong>属性(atrrbile)</strong>的形式来实现的,我在使用ionic框架的时候,里面有很多自定义的标签、比如:<strong><code class="html language-html" data-lang="html"><ion-content></code></strong><code class="html language-html" data-lang="html"><strong></ion-content></strong>。这也是一个指令,他是通过html<strong>元素(element)</strong>来实现的。除了这两个之外,指令还支持<strong>class</strong>(html标签的class属性)、<strong>commment</strong>(html中的注释)来实现。</code></p>
<p>在JS代码中,restrict可以有以下赋值:</p>
<div class="cnblogs_code">
<pre> restrict: 'AE',<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 指令类型E:element A:attribute M:comment C: class</span></pre>
</div>
<p>可以是多个restrict: 'AEMC',也可以是一个restrict: 'E'。在html中对应的写法为:</p>
<table style="height: 110px; width: 743px" border="1" align="center">
<tbody>
<tr>
<td>字母</td>
<td>声明风格</td>
<td>事例</td>
</tr>
<tr>
<td>E</td>
<td>元素</td>
<td><my-memu title="products"></my-memu></td>
</tr>
<tr>
<td>A</td>
<td>属性</td>
<td><div my-memu="products"></div></td>
</tr>
<tr>
<td>C</td>
<td>样式</td>
<td><div class="my-memu:products"></div></td>
</tr>
<tr>
<td>M</td>
<td>注释</td>
<td><!-- directive my-memu products --></td>
</tr>
</tbody>
</table>
<hr>
<p>template:</p>
<p>同一个指令中只能<strong>template</strong>和<strong>templateUrl</strong>只能选其一。</p>
<p>template为模板内容。即你要在指令所在的容器中插入的html代码。</p>
<p>template属性接收一个字符串,类似这样: <span style="color: rgba(0, 128, 0, 1)">template: '<div>我是指令生成的内容</div>';</span></p>
<hr>
<p> </p>
<p>templateUrl:</p>
<p>为从指定地址获取模板内容。即你要在指令所在的容器中插入的一个.html文件。</p>
<p>有了templateUrl我们就可以将想实现的内容写成一个单独的html模版,在需要的地方插入</p>
<div class="cnblogs_code">
<pre>angular.module('module1').run(['$templateCache', <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> ($templateCache) {
$templateCache.put(</span>'test.html', '<div>This is templateUrl</div>'<span style="color: rgba(0, 0, 0, 1)">);
}]);
angular.module(</span>'module1').directive("testDirective", ["$parse", "$http"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> ($parse, $http) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
restrict: </span>"E"<span style="color: rgba(0, 0, 0, 1)">,
templateUrl: </span>"test.html"<span style="color: rgba(0, 0, 0, 1)">
};
}]);</span></pre>
</div>
<hr>
<p>replace:</p>
<p>是否用模板替换当前元素。true : 将指令标签替换成temple中定义的内容,页面上不会再有<my-directive>标签;false :则append(追加)在当前元素上,即模板的内容包在<my-directive>标签内部。默认false。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> app = angular.module("app"<span style="color: rgba(0, 0, 0, 1)">, [])
.directive(</span>"hello", <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> () {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> option =<span style="color: rgba(0, 0, 0, 1)"> {
restrict: </span>"AECM"<span style="color: rgba(0, 0, 0, 1)">,
template: </span>"<h3>Hello, Directive</h3>"<span style="color: rgba(0, 0, 0, 1)">,
replace: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这里replace为true,所以原来的内容会被template代替</span>
<span style="color: rgba(0, 0, 0, 1)"> };
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> option;
})</span></pre>
</div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">html</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">hello</span><span style="color: rgba(0, 0, 255, 1)">></span>我是原来的内容<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">hello</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">消失</span><span style="color: rgba(0, 128, 0, 1)">--></span><span style="color: rgba(0, 0, 0, 1)">
===> 变成</span><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">h3</span><span style="color: rgba(0, 0, 255, 1)">></span>Hello, Directive<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">h3</span><span style="color: rgba(0, 0, 255, 1)">></span> 如果replace为false ===><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">hello</span><span style="color: rgba(0, 0, 255, 1)">><</span><span style="color: rgba(128, 0, 0, 1)">h3</span><span style="color: rgba(0, 0, 255, 1)">></span>Hello, Directive<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">h3</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">hello</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">html</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<hr>
<p>transculde:</p>
<p>是否使用ng-transculde来包含html中指令包含的原有的内容,接收两个参数true/false</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> app = angular.module("app"<span style="color: rgba(0, 0, 0, 1)">, [])
.directive(</span>"hello", <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> () {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> option =<span style="color: rgba(0, 0, 0, 1)"> {
restrict: </span>"AECM"<span style="color: rgba(0, 0, 0, 1)">,
template: </span>"<h3>Hello, Directive</h3><span ng-transclude></span>"<span style="color: rgba(0, 0, 0, 1)">,
transculde: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这里transculde为true,所以原来的内容会被放在有ng-transclude属性的标签内</span>
<span style="color: rgba(0, 0, 0, 1)"> };
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> option;
})</span></pre>
</div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">html</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">head</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">hello</span><span style="color: rgba(0, 0, 255, 1)">></span>我是原来的内容<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">hello</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)">
===> 变成</span><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">hello</span><span style="color: rgba(0, 0, 255, 1)">><</span><span style="color: rgba(128, 0, 0, 1)">h3</span><span style="color: rgba(0, 0, 255, 1)">></span>Hello, Directive<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">h3</span><span style="color: rgba(0, 0, 255, 1)">><</span><span style="color: rgba(128, 0, 0, 1)">span </span><span style="color: rgba(255, 0, 0, 1)">ng-transclude</span><span style="color: rgba(0, 0, 255, 1)">></span>我是原来的内容<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">span</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">hello</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">html</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<hr>
<p>scope:</p>
<p><strong>directive</strong> 默认能共享<strong>父 scope</strong> 中定义的属性,例如在模版中直接使用<strong>父 scope 中的对象和属性</strong>。通常使用这种直接共享的方式可以实现一些简单的 directive 功能。</p>
<p>但是,当你要创建一个可以重复使用的directive的时候,就不能依赖于父scope了,因为在不同的地方使用directive对应的父scope不一样。</p>
<p>所以你需要一个隔离的scope,我们可以向下面这样来定义我们的scope。</p>
<div class="cnblogs_code">
<pre>module1.directive("testDirective", <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> () {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
scope: {
</span>"":"<span style="color: rgba(255, 0, 0, 1)">@</span>"<span style="color: rgba(0, 0, 0, 1)">,
</span>"":"<span style="color: rgba(255, 0, 0, 1)">&</span>"<span style="color: rgba(0, 0, 0, 1)">,
</span>"":"<span style="color: rgba(255, 0, 0, 1)">=</span>"<span style="color: rgba(0, 0, 0, 1)">
},
template: </span>'Say:{{value}}'<span style="color: rgba(0, 0, 0, 1)">
}
});</span></pre>
</div>
<p>这样就很方便的将我们directive的上下文scope给定义出来了,但是,如果我想将父scope中的属性传递给directive的scope怎么办呢?</p>
<p>directive 在使用隔离 scope 的时候,提供了三种方法同隔离之外的地方交互:</p>
<ul>
<li>@ 指令中定一个变量用来获取父scope中的值,是单项绑定的,指令中的值改变,父scope中的值不变</li>
</ul>
<div class="cnblogs_code">
<pre><script type="text/ng-template" id="scopeTemplate">
<div class="panel-body">
<p>Data Value: {{local}}</p>
<p>Data Value: {{secondLocal}}</p>
</div>
</script>
<script type="text/javascript"><span style="color: rgba(0, 0, 0, 1)">
angular.module(</span>"exampleApp"<span style="color: rgba(0, 0, 0, 1)">, [])
.directive(</span>"scopeDemo", <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> () {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
template: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> angular.element(
document.querySelector(</span>"#scopeTemplate"<span style="color: rgba(0, 0, 0, 1)">)).html();
},
scope: {
local: </span>"@nameprop"<span style="color: rgba(0, 0, 0, 1)">,
secondLocal:</span>"@secondNameprop"<span style="color: rgba(0, 0, 0, 1)">
}
}
})
.controller(</span>"scopeCtrl", <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> ($scope) {
$scope.data </span>= { name: "Adam"<span style="color: rgba(0, 0, 0, 1)"> };
});
</span></script></pre>
</div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">body </span><span style="color: rgba(255, 0, 0, 1)">ng-controller</span><span style="color: rgba(0, 0, 255, 1)">="scopeCtrl"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">div </span><span style="color: rgba(255, 0, 0, 1)">class</span><span style="color: rgba(0, 0, 255, 1)">="panel panel-default"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">div </span><span style="color: rgba(255, 0, 0, 1)">class</span><span style="color: rgba(0, 0, 255, 1)">="panel-body"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)">
Direct Binding: </span><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">input </span><span style="color: rgba(255, 0, 0, 1)">ng-model</span><span style="color: rgba(0, 0, 255, 1)">="data.name"</span> <span style="color: rgba(0, 0, 255, 1)">/></span><span style="color: rgba(0, 0, 0, 1)"> // 这里改变下面会跟着改变
</span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">div </span><span style="color: rgba(255, 0, 0, 1)">class</span><span style="color: rgba(0, 0, 255, 1)">="panel-body"</span><span style="color: rgba(255, 0, 0, 1)"> scope-demo nameprop</span><span style="color: rgba(0, 0, 255, 1)">="{{data.name}}"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> // 跟着上面数值动态变化
</span><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">div </span><span style="color: rgba(255, 0, 0, 1)">class</span><span style="color: rgba(0, 0, 255, 1)">="panel-body"</span><span style="color: rgba(255, 0, 0, 1)"> scope-demo second-nameprop</span><span style="color: rgba(0, 0, 255, 1)">="{{data.name}}"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)"> // 跟着上面数值动态变化
</span><span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<p>指令中的local通过nameprop获得外部属性data.name,所以在控制器中的data.name变化时,指令中的local也会跟着改变;(但如果是只改变local的值,外界的data.name是不会变的);</p>
<ul>
<li>& 调用父级作用域中的方法(function);</li>
</ul>
<div class="cnblogs_code">
<pre><script type="text/ng-template" id="scopeTemplate">
<div class="panel-body">
<p>Name: {{local}}, City: {{cityFn()}}</p>
</div>
</script>
<script type="text/javascript"><span style="color: rgba(0, 0, 0, 1)">
angular.module(</span>"exampleApp"<span style="color: rgba(0, 0, 0, 1)">, [])
.directive(</span>"scopeDemo", <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> () {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
template: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> () {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> angular.element(
document.querySelector(</span>"#scopeTemplate"<span style="color: rgba(0, 0, 0, 1)">)).html();
},
scope: {
local: </span>"=nameprop"<span style="color: rgba(0, 0, 0, 1)">,
cityFn: </span>"&city"<span style="color: rgba(0, 0, 0, 1)">
}
}
})
.controller(</span>"scopeCtrl", <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> ($scope) {
$scope.data </span>=<span style="color: rgba(0, 0, 0, 1)"> {
name: </span>"Adam"<span style="color: rgba(0, 0, 0, 1)">,
defaultCity: </span>"London"<span style="color: rgba(0, 0, 0, 1)">
};
$scope.getCity </span>= <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (name) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> name == "Adam" ? $scope.data.defaultCity : "Unknown"<span style="color: rgba(0, 0, 0, 1)">;
}
});
</span></script></pre>
</div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">body </span><span style="color: rgba(255, 0, 0, 1)">ng-controller</span><span style="color: rgba(0, 0, 255, 1)">="scopeCtrl"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">div </span><span style="color: rgba(255, 0, 0, 1)">class</span><span style="color: rgba(0, 0, 255, 1)">="panel panel-default"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">div </span><span style="color: rgba(255, 0, 0, 1)">class</span><span style="color: rgba(0, 0, 255, 1)">="panel-body"</span><span style="color: rgba(0, 0, 255, 1)">></span><span style="color: rgba(0, 0, 0, 1)">
Direct Binding: </span><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">input </span><span style="color: rgba(255, 0, 0, 1)">ng-model</span><span style="color: rgba(0, 0, 255, 1)">="data.name"</span> <span style="color: rgba(0, 0, 255, 1)">/></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">div </span><span style="color: rgba(255, 0, 0, 1)">class</span><span style="color: rgba(0, 0, 255, 1)">="panel-body"</span><span style="color: rgba(255, 0, 0, 1)"> scope-demo
city</span><span style="color: rgba(0, 0, 255, 1)">="getCity(data.name)"</span><span style="color: rgba(255, 0, 0, 1)"> nameprop</span><span style="color: rgba(0, 0, 255, 1)">="data.name"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">body</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<ul>
<li>= 指令中定一个变量用来获取父scope中的值,是双项绑定的,指令中的值改变,父scope中的值不变</li>
</ul>
<p>这里所有指令作用域跟外界交互都是通过<strong>属性值</strong>传入的:<div class="panel-body" scope-demo <strong>city</strong><strong>=</strong>"getCity(data.name)"<em id="__mceDel"><strong>nameprop</strong>="data.name"></div></em></p>
<hr>
<p> <em id="__mceDel">controller link:</em></p>
<pre>controller: function ($scope, $element, $attrs) {}三个参数<br>link: function (scope, element, attrs, controller) {}四个参数</pre>
<p>第一次尝试:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">custom-directive</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">custom-directive</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">angular
.module(</span>'app'<span style="color: rgba(0, 0, 0, 1)">,[])
.directive(</span>'customDirective'<span style="color: rgba(0, 0, 0, 1)">, customDirective);
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> customDirective() {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> directive =<span style="color: rgba(0, 0, 0, 1)"> {
restrict: </span>'EA'<span style="color: rgba(0, 0, 0, 1)">,
template: </span>'<div>{{vm.test}}</div>'<span style="color: rgba(0, 0, 0, 1)">,
link: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){},
controller: directiveController
};
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> directive;
}
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> directiveController() {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> vm = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">;
vm.test </span>= "I'm from Controller"<span style="color: rgba(0, 0, 0, 1)">;
}</span></pre>
</div>
<p><img src="https://img2018.cnblogs.com/blog/1137416/201906/1137416-20190617163856163-1308611797.png"></p>
<p>第二次尝试:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">angular
.module(</span>'app'<span style="color: rgba(0, 0, 0, 1)">,[])
.directive(</span>'customDirective'<span style="color: rgba(0, 0, 0, 1)">, customDirective);
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> customDirective() {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> directive =<span style="color: rgba(0, 0, 0, 1)"> {
restrict: </span>'EA'<span style="color: rgba(0, 0, 0, 1)">,
template: </span>'<div>{{test}}</div>'<span style="color: rgba(0, 0, 0, 1)">,
link: directiveLink
};
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> directive;
}
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> directiveLink(scope,elem,attr) {
scope.test </span>= "I'm from Link"<span style="color: rgba(0, 0, 0, 1)">;
}</span></pre>
</div>
<p><img src="https://img2018.cnblogs.com/blog/1137416/201906/1137416-20190617163956096-1566465312.png"></p>
<p><span style="color: rgba(255, 0, 0, 1)">到这里,我们不仅要开始思索:指令中的controller和link都可以实现同样的效果,那在指令中放这两个属性干嘛?我们的代码到底是放在controller还是link中?</span></p>
<p><span style="color: rgba(0, 128, 128, 1)">我们首先来看看当二者一起使用时,呈现结果的顺序即在编译前后生成的顺序。</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">angular
.module(</span>'app'<span style="color: rgba(0, 0, 0, 1)">,[])
.directive(</span>'customDirective'<span style="color: rgba(0, 0, 0, 1)">, customDirective);
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> customDirective() {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> directive =<span style="color: rgba(0, 0, 0, 1)"> {
restrict: </span>'EA'<span style="color: rgba(0, 0, 0, 1)">,
template: </span>'<div>xpy0928{{test}}</div>'<span style="color: rgba(0, 0, 0, 1)">,
link: directiveLink,
controller:directiveController
};
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> directive;
}
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> directiveController($scope){
$scope.test </span>= " from contrller cnblogs"<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> directiveLink(scope,elem,attr) {
scope.test </span>= scope.test + ",and from link cnblogs"<span style="color: rgba(0, 0, 0, 1)">;
}</span></pre>
</div>
<p><img src="https://img2018.cnblogs.com/blog/1137416/201906/1137416-20190617164141783-220517661.png"></p>
<p><span style="color: rgba(255, 0, 0, 1)">我们由此得出结论:编译之前执行控制器(controller),编译之后执行链接(link)。</span></p>
<p><span style="color: rgba(0, 128, 0, 1)">但是我们还未从根本上解决问题,在controller和link应该放哪些代码?我们接下来再看一个例子:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> app = angular.module('app'<span style="color: rgba(0, 0, 0, 1)">,[]);
app.directive(</span>'customDirective'<span style="color: rgba(0, 0, 0, 1)">, customDirective);
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> customDirective() {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> directive =<span style="color: rgba(0, 0, 0, 1)"> {
restrict: </span>'EA'<span style="color: rgba(0, 0, 0, 1)">,
template: </span>'<child-directive><child-directive>'<span style="color: rgba(0, 0, 0, 1)">,
controller: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">($scope, $element) {
$element.find(</span>'span').text('hello cnblogs!'<span style="color: rgba(0, 0, 0, 1)">);
}
};
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> directive;
}
app.directive(</span>"childDirective"<span style="color: rgba(0, 0, 0, 1)">,childDirective);
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> childDirective() {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> directive =<span style="color: rgba(0, 0, 0, 1)"> {
restrict: </span>'EA'<span style="color: rgba(0, 0, 0, 1)">,
template: </span>'<h1>hello xpy0928</h1>'<span style="color: rgba(0, 0, 0, 1)">,
replace: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
link: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">($scope, $element, attr) {
$element.replaceWith(angular.element(</span>'<span>' + $element.text() + '</span>'<span style="color: rgba(0, 0, 0, 1)">));
}
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> directive;
}</span></pre>
</div>
<p>此时结果应该还是hello xpy0928还是hello cnblogs呢?我们看下结果</p>
<p><img src="https://img2018.cnblogs.com/blog/1137416/201906/1137416-20190617164623317-317682653.png"></p>
<p><span style="color: rgba(255, 0, 0, 1)">我们再来将如上进行修改看看:</span></p>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> app = angular.module('app'<span style="color: rgba(0, 0, 0, 1)">,[]);
app.directive(</span>'customDirective'<span style="color: rgba(0, 0, 0, 1)">, customDirective);
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> customDirective() {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> directive =<span style="color: rgba(0, 0, 0, 1)"> {
restrict: </span>'EA'<span style="color: rgba(0, 0, 0, 1)">,
template: </span>'<child-directive><child-directive>'<span style="color: rgba(0, 0, 0, 1)">,
link: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(scope, el) {
el.find(</span>'span').text('hello cnblogs!'<span style="color: rgba(0, 0, 0, 1)">);
}
};
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> directive;
}
app.directive(</span>"childDirective"<span style="color: rgba(0, 0, 0, 1)">,childDirective);
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> childDirective() {
</span><span style="color: rgba(0, 0, 255, 1)">var</span> directive =<span style="color: rgba(0, 0, 0, 1)"> {
restrict: </span>'EA'<span style="color: rgba(0, 0, 0, 1)">,
template: </span>'<h1>hello xpy0928</h1>'<span style="color: rgba(0, 0, 0, 1)">,
replace: </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
link: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">($scope, $element, attr) {
$element.replaceWith(angular.element(</span>'<span>' + $element.text() + '</span>'<span style="color: rgba(0, 0, 0, 1)">));
}
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> directive;
}</span></pre>
</div>
<p><img src="https://img2018.cnblogs.com/blog/1137416/201906/1137416-20190617164655482-1255709703.png"></p>
<p><span style="color: rgba(255, 0, 0, 1)">为什么会出现如此情况?因为在controller函数中此时所有child-directive指令中的link函数还未运行所以此时替换无效</span></p>
<p> 由此我们可以基本得出在controller和link中应该写什么代码的结论:</p>
<p>(1)在controller写业务逻辑(我们明白业务逻辑大部分是放在服务中),这里所说的业务逻辑乃是为呈现视图之前而准备的数据或者是与其他指令进行数据交互而暴露这个api。</p>
<p>(2)在link中主要操作DOM。</p>
<hr>
<p> </p>
<p>controllerAs:</p>
<p>controller as引入的意义和方法 </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">div </span><span style="color: rgba(255, 0, 0, 1)">ng-app</span><span style="color: rgba(0, 0, 255, 1)">="myApp"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">div </span><span style="color: rgba(255, 0, 0, 1)">ng-controller</span><span style="color: rgba(0, 0, 255, 1)">="firstController"</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">div </span><span style="color: rgba(255, 0, 0, 1)">book-list</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span>
<span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<div class="cnblogs_code">
<pre>angular.module('myApp'<span style="color: rgba(0, 0, 0, 1)">,[])
.directive(</span>'bookList',<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
restrict:</span>'ECAM'<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">此处定义了该指令的controller属性</span>
controller:<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">($scope){
$scope.books</span>=<span style="color: rgba(0, 0, 0, 1)">[
{name:</span>'php'<span style="color: rgba(0, 0, 0, 1)">},
{name:</span>'javascript'<span style="color: rgba(0, 0, 0, 1)">},
{name:</span>'java'<span style="color: rgba(0, 0, 0, 1)">}
];
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.addBook=<span style="color: rgba(0, 0, 255, 1)">function</span>(){ <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">或者 scope.addBook=...</span>
alert('test'<span style="color: rgba(0, 0, 0, 1)">);
}
},
controllerAs:</span>'bookListController', <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">给当前controller起个名称</span>
template:'<ul><li ng-repeat="book in books">{{ book.name }}</li></ul>'<span style="color: rgba(0, 0, 0, 1)">,
replace:</span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">link中注入 bookListController ,就可以使用它的方法了</span>
link:<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(scope,iElement,iAttrs,bookListController){
iElement.on(</span>'click'<span style="color: rgba(0, 0, 0, 1)">,bookListController.addBook);
}
}
})
.controller(</span>'firstController',['$scope',<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">($scope){
}])</span></pre>
</div>
<hr>
<p>require:</p>
<p>谈require选项之前,应该先说说controller选项,controller选项允许指令对其他指令提供一个类似接口的功能,只要别的指令(甚至是自己)有需要,就可以获取该controller,将其作为一个对象,并取得其中的所有内容。而require就是连接两个指令的锁链,<span style="color: rgba(255, 0, 0, 1)">它可以选择性地获取指令中已经定义好的controller,并作为link函数的第四个参数传递进去</span>,link函数的四个参数分别为scope,element,attr和someCtrl,最后一个就是通过require获取的controller的名字,对于controller的名字,可以在指令中用controllerAs选项进行定义,这是发布控制器的关键.</p>
<p> 具体如何获取controller呢?require选项的值可以分别用前缀?、^ 和?^进行修饰,也可以不修饰。</p>
<p> 如果不进行修饰,比如require:'thisDirective',那么require只会在当前指令中查找控制器</p>
<p> 如果想要指向上游的指令,那么就是用^进行修饰,比如require:'^parentDirective',如果没有找到,那就会抛出一个错误。</p>
<p> 如果使用?前缀,就意味着如果在当前指令没有找到控制器,就将null作为link的第四个参数;</p>
<p> 那么,如果将?和^结合起来,我们就可以既指定上游指令,又可以在找不到时,不抛出严重的错误。</p>
<p> 现在问题来了,如果我想指定多于一个指令,那怎么办呢?这时,我们可以将需要的指令放进一个数组中,例如:require:['^?firstDirective','^?secondDirective','thisDirective'],这不正是依赖注入的形式吗?但要注意一点,如果使用这种写法的话,原先指令中发布的控制器的名字,即controllerAs选项,就失去意义了。此时,我们在link中调用这些指令的controller的方法变为:先为上边的数组定义一个名字,接着根据其下标号来指定具体的某个指令。类似于:ctrlList。</p>
<p> </p>
<p> 假如我们现在需要编写两 个指令,在linking函数中有很多重合的方法,为了避免重复自己(著名的DRY原则),我们可以将这个重复的方法写在第三个指令的 controller中,然后在另外两个需要的指令中require这个拥有controller字段的指令,最后通过linking函数的第四个参数就可以引用这些重合的方法。代码的结构大致如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> app = angular.modeule('myapp'<span style="color: rgba(0, 0, 0, 1)">,[]);
app.directive(</span>'common',<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
...
controller: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">($scope){
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.method1 = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){
};
</span><span style="color: rgba(0, 0, 255, 1)">this</span>.method2 = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){
};
},
...
}
});
app.directive(</span>'d1',<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
...
require: </span>'?^common'<span style="color: rgba(0, 0, 0, 1)">,
link: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(scope,elem,attrs,common){
scope.method1 </span>=<span style="color: rgba(0, 0, 0, 1)"> common.method1;
..
},
...
}
});</span></pre>
</div>
<hr>
<p> </p><br><br>
来源:https://www.cnblogs.com/ms-grf/p/11040964.html
頁:
[1]