angularJS系列之指令directive应用实例

代码结构

angularJS系列之指令directive应用实例_第1张图片

html页面代码


<html ng-app="demoForDirective">
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <script src="./lib/angular.js">script>
    <script src="./js/app.js">script>
    <script src="./js/controller.js">script>
head>
<body>
<div ng-controller='demoForDirectiveController'>
    
    <testdirective testdirective-title='title'>
        {{text}}
    testdirective>
div>
<div>
    
    分数:<input type="text" attrsdirective/><br/>
div>

<div ng-controller="SomeController">
    <accordion>
        <expander class="expander"
                  ng-repeat="expander in expanders"
                  expander-title="expander.title">
            {{expander.text}}
        expander>
    accordion>
div>
body>
html>

app.js代码

/**
 * Created by jywl on 2016/7/7.
 */
var demoForDirective = angular.module('demoForDirective', ['demoForDirective.controller']);
demoForDirective.directive('testdirective', function () {
    return {
        restrict: 'EA',
        replace: true,
        transclude: true,
        scope: {
            title: '=testdirectiveTitle'
        },
        template: '
' + '
{{title}}
'
+ '
'
+ '
'
, link: function (scope, element, attrs) { scope.showMe = false; scope.toggle = function toggle() { scope.showMe = !scope.showMe; } } } }); demoForDirective.directive('attrsdirective', function () { return { link: function (scope, elements, attrs, controller) { elements[0].onkeyup = function () { //从元素列表中获取元素,并绑定相应的事件 //下面的意思是,如果输入10以内的数,则输入框边框颜色不变,否则变为红色 if (isNaN(this.value) || this.value < 1 || this.value > 10) { this.style.borderColor = 'red'; } else { this.style.borderColor = ''; } }; } } }); demoForDirective.directive('accordion', function () { return { restrict: 'EA', replace: true, transclude: true, template: '
'
, controller: function () { //声明一个内部的controller,用于传递值和方法 var expanders = []; this.gotOpened = function (selectedExpander) { //angularJS的forEach用法 /*var objs =[{a:1},{a:2}]; angular.forEach(objs, function(data,index,array){ //data等价于array[index] console.log(data.a+'='+array[index].a); }); 参数如下: objs:需要遍历的集合 data:遍历时当前的数据 index:遍历时当前索引 array:需要遍历的集合,每次遍历时都会把objs原样的传一次。 * */ angular.forEach(expanders, function (expander) { if (selectedExpander != expander) { expander.showMe = false; } }); } this.addExpander = function (expander) { expanders.push(expander); } } } }); demoForDirective.directive('expander', function () { return { restrict: 'EA', replace: true, transclude: true, require: '^?accordion',//意思是将accordion的控制器传到指令中,从而在下方使用它的函数 ^的意思是需要遍历dom树,?的意思是找不到不报错 scope: { title: '=expanderTitle' }, template: '
' + '
{{title}}
'
+ '
'
+ '
'
, link: function (scope, element, attrs, accordionController) { scope.showMe = false; accordionController.addExpander(scope); scope.toggle = function toggle() { scope.showMe = !scope.showMe; accordionController.gotOpened(scope); } } } });

controller.js代码

/**
 * Created by jywl on 2016/7/7.
 */
angular.module('demoForDirective.controller', [])
    .controller('demoForDirectiveController', function ($scope) {
        $scope.title = '点击展开';
        $scope.text = '这里是内部的内容。';
    })

    .controller('SomeController', function ($scope) {
        $scope.expanders = [
            {title: 'click me', text: 'one click'},
            {title: 'click me two', text: 'two click'},
            {title: 'click me three', text: 'three click'}];
    });

代码说明

主要详解app.js中关于指令的代码,大部分代码都有注释,如果还有不清楚的可以留言,我看到会及时回复的。

directive的参数说明

priority(优先级)- 当有多个directive定义在同一个DOM元素时,有时需要明确它们的执行顺序。这属性用于在directive的compile function调用之前进行排序。如果优先级相同,则执行顺序是不确定的(经初步试验,优先级高的先执行,同级时按照类似栈的“后绑定先执行”。另外,测试时有点不小心,在定义directive的时候,两次定义了一个相同名称的directive,但执行结果发现,两个compile或者link function都会执行)。据官方说,ng-repeate的优先级是1000。该属性默认值为0。

terminal(最后一组)- 如果设置为”true”,则表示当前的priority将会成为最后一组执行的directive。任何directive与当前的优先级相同的话,他们依然会执行,但顺序是不确定的(虽然顺序不确定,但基本上与priority的顺序一致。当前优先级执行完毕后,更低优先级的将不会再执行)。

scope - 如果设置为:
true - 将为这个directive创建一个新的scope作用域,而不是继承父作用域。

false - 默认值,使用现有的scope作用域。

{/属性名和绑定风格/} - 独立的scope。

独立scope与一般的scope的区别在于它不是通过原型继承于父scope的。这对于创建可复用的组件是很有帮助的,可以有效防止读取或者修改父级scope的数据。

绑定策略

@或@attr - 建立一个local scope property到DOM属性的绑定。因为属性值总是String类型,所以这个值总是返回一个字符串。如果没有通过@attr指定属性名称,那么本地名称将与DOM属性的名称一致。例如,widget的scope定义为:{localName:’@myAttr’}。那么,widget scope property的localName会映射出”hello {{name}}”转换后的真实值。name属性值改变后,widget scope的localName属性也会相应地改变(仅仅单向,与下面的”=”不同)。name属性是在父scope读取的。

=或=expression(绑定当前属性,它带来一个来自指令父scope的属性) - 在本地scope属性与parent scope属性之间设置双向的绑定。如果没有指定attr名称,那么本地名称将与属性名称一致。例如,widget定义的scope为:{localModel:’=myAttr’},那么widget scope property “localName”将会映射父scope的“parentModel”。如果parentModel发生任何改变,localModel也会发生改变,反之亦然。(双向绑定)

&或&attr - 传递一个来自父scope的函数,稍后调用。

controller - controller 构造函数。controller会在pre-linking步骤之前进行初始化,并允许其他directive通过指定名称的require进行共享(看下面的require属性)。这将允许directive之间相互沟通,增强相互之间的行为。

controller默认注入了以下本地对象:
$scope - 与当前元素结合的scope
$element - 当前的元素
$attrs - 当前元素的属性对象
$transclude - (A transclude linking function pre-bound to the correct transclusion scope)

require - 请求另外的controller,传入当前directive的linking function中。require需要传入一个directive controller的名称。如果找不到这个名称对应的controller,那么将会抛出一个error。名称可以加入以下前缀:
? - 不要抛出异常。这使这个依赖变为一个可选项。
^ - 允许查找父元素的controller

restrict - EACM的子集的字符串,它限制directive为指定的声明方式。如果省略的话,directive将仅仅允许通过属性声明:
E - 元素名称:
A - 属性名:


C - class名:

M - 注释 :

template - 如果replace 为true,则将模版内容替换当前的HTML元素,并将原来元素的属性、class一并迁移;如果为false,则将模版元素当作当前元素的子元素处理。

templateUrl - 与template基本一致,但模版通过指定的url进行加载。因为模版加载是异步的,所以compilation、linking都会暂停,等待加载完毕后再执行。

replace - 如果设置为true,那么模版将会替换当前元素,而不是作为子元素添加到当前元素中。(注:为true时,模版必须有一个根节点)

transclude - 编译元素的内容,使它能够被directive所用。(如果当前元素,希望其他directive调用,就将其设为true,并在元素的节点上,增加

就好,更高级的用法,目前我还在学习中)
true - 转换这个directive的内容。(这个感觉上,是直接将内容编译后搬入指定地方)
element - 转换整个元素,包括其他优先级较低的directive。(像将整体内容编译后,当作一个整体(外面再包裹p),插入到指定地方)

compile - 编译函数,整个运行周期中只执行一遍。(一般情况下,用compile即可。)

link - 链接函数,可以多次执行。具体用法参照上文代码

你可能感兴趣的:(angularJS)