AngularJs中directive详解

API

app.directive('helloWorld', function() {
    return {
        restrict: string,
        priority: number,        
        template: string,
        templateUrl: string,
        replace: bool,
        transclude: bool,
        scope: bool or object,
        requirestring,
        controller: function (scope,elem,attrs,transclude){},
        compile: function(){
            return {
              pre: function(scope, iElem, iAttrs){

              },
              post: function(scope, iElem, iAttrs){

                }
            }
        },
        link: function(scope, elem, attrs) {},

    };
});

restrict: 指令运用时显示的方式

priority: 一条语句中包含了多条指令时,执行的先后顺序

template: 字符串作为模板

templateUrl: 指定url页面作为模板

replace: 是否替换指令所在元素

transclude: 把指令元素中原来的子节点移动到一个新的模板内部

scope:新的作用域

require:必须存在另外的指令,此指令才执行

controller:控制器

compile: 编译函数

link: 链接函数

restrict

restrict是用来表明使用指令的方式,共有E、A、C、M四种风格。

app.directive('directiveTest', function () {
    return {
        restrict: 'EACM',
        template: '<div>test</div>'
    };
});

使用

<!--E方式-->
<directive-test></directive-test>
<!--A方式-->
<div directive-test></div>
<!--C方式-->
<div class="directive-test"></div>
<!--M方式 我使用的1.3版本没有作用-->
<!-- directive: directive-test -->

priority

当我们在一条语句中使用了多个指令时,需要进行执行顺序优先级的判断,默认值为0,例如:

app.directive('directiveOne', function () {
    return {
        restrict: 'A',
        priority:1,
        template: '<div>one</div>'
    };
});

app.directive('directiveTwo', function () {
    return {
        restrict: 'A',
        priority:2,
        template: '<div>two</div>'
    };
});

使用

<div directive-one directive-two></div>

结果页面只会显示two,因为先执行directiveTwo(此处两个指令功能冲突)。

<div directive-one="" directive-two=""><div>two</div></div>

template与templateUrl

template与templateUrl都是进行模板定义,区别在于一个使用字符串,一个引用url地址。

app.directive('directiveOne', function () {
    return {
        restrict: 'A',      
        template: '<div>one</div>',
        templateUrl: 'xxx/xxxx/test.html'
    };
});

当template与templateUrl同时存在时,系统会选择使用template。

replace

replace用于是否替换指令所在元素。

app.directive('directiveOne', function () {
    return {
        restrict: 'A',
        template: '<div>one</div>',
        replace:true
    };
});

replace false(默认值):

<div directive-one="" class="ng-scope"><div>one</div></div>

replace true:

<div directive-one="" class="ng-scope">one</div>

transclude

transclude是否使用原有内容,通过ng-transclude调用。

app.directive('directiveOne', function () {
    return {
        restrict: 'A',
        template: '<div>one<span ng-transclude></span></div>',
        transclude:true
    };
});

<div directive-one>原有内容</div>

结果

<div directive-one="" class="ng-scope">
    <div>
        one
            <span ng-transclude="">
                <span class="ng-scope">原有内容</span>
        </span>
    </div>
</div>

one原有内容

注意:ng-transclude不能放在根dom中,例如下面是会报错的

template: '<div ng-transclude></div>',

compile与link

compile与link是对dom的操作支出,也是指令的核心点。compile侧重于对模板本身进行操作,而link侧重于模板与数据进行关联。

首先我们需要了解angular初始化分为三个步骤:加载脚本,编译阶段,链接阶段

  1. 加载脚本:加载angular库,查找ng-app确定边界。
  2. 编译阶段:遍历dom,识别template、replace等进行dom的转化,执行compile函数。
  3. 链接阶段:运行link函数,对dom进行监听。

compile函数包含两个返回函数

compile: function(){
    return {
        pre: function(scope, iElem, iAttrs){

        },
        post: function(scope, iElem, iAttrs){

        }
    }
},            
  1. pre:函数能够保证在element实例上以及它的所有子指令的post运行之前执行。
  2. post:当ng遍历完所有的dom并运行完所有的compile函数之后,就反向调用相关联的post函数.
  3. compile只会调用一次,而link调用次数与调用次数相关(一个page内)。

也就是当同一个dom存在多条指令时,directiveOne、directiveTwo、directiveThree,执行顺序如下:

directiveOne.compile->directiveTwo.compile->directiveThree.compile

->directiveOne.pre->directiveTwo.pre->directiveThree.pre

->directiveThree.post->directiveTwo.post->directiveOne.post

link函数

link: function(scope, elem, attrs) {},

我测试的测过好像是link与compile不能共存

controller

是创建一个改dom为边界的controller层。

controller:'controllerName'

或者是

controller:function($scope, $element,$attrs,$transclude){

}

require

通过require属性语法,其他指令可以把这个控制器传递给自己。

形式:require:’^?directiveName’

  1. directiveName:驼峰法则命名制定控制器带有哪条指令。
  2. ^:默认是从同一个元素的命名指令中获取控制器。添加这个之后,遍历dom树进行查找
  3. ?:如果没有找到控制器,会抛出异常,添加之后,则不会抛出异常。

举例如下:

app.directive('out', function () {
    return {
        restrict: 'EA',
        transclude:true,
        replace:true,
        template: '<div><div ng-transclude></div></div>',
        controller:function($scope, $element,$attrs,$transclude){
            this.print = function(){
                console.log("parent")
            }
        }
    };
});

app.directive('in', function () {
    return {
        restrict: 'EA',
        transclude:true,
        replace:true,
        require:'^?out',
        template: '<div><div ng-click="print()">click(点击)</div>' +
            '<div  ng-transclude></div></div>',
        link:function(scope,element,attrs,ctrl){
            scope.print = function(){
                console.log("self");
                ctrl.print();
            }
        }
    };
});

运用

<out>
    <in></in>
</out>

效果

click(点击)

控制台输出:  
self
parent

scope

scope可以定义scope的作用域,有三种类型

  1. scope:fasle(默认值),scope为dom元素上原有的scope对象。
  2. scope:true,新创建一个scope对象,继承外层scope。
  3. scope:{xxxx},独立scope对象,不会继承外层scope。

false:

继承外层scope:指令中对scope进行修改,也会修改外层scope对象数值。

app.directive('directiveOne', function () {
    return {
        restrict: 'A',
        template: '<div>one </div>'
    };
});

app.controller('testCtrl', function ($scope, $http, $location, $rootScope) {
    $scope.data ="controller定义的内容"
})


<div ng-app="testCtrl">    
    <div directive-one></div>    
</div>

结果

one controller定义的内容

true:

继承外层scope:指令中对scope进行修改,则不会改变外城scope,实际上是创建了一个新的域,只是指令初始化时使用了外层scope的对象数值。

{xxxxx}

在我看来这个作用就是可以从指令dom上获取数据。

绑定策略:

  1. @: 把当前属性作为字符串进行传递
  2. =: 读取父scope的一个对象
  3. &: 传递一个父scope的函数

例如:

app.controller('testCtrl', function ($scope, $http, $location, $rootScope) {
    $scope.data ="controller定义的内容"
    $scope.fun = function(){
        console.log("this is a function")
    }
})

<div ng-app="testCtrl">
    <div directive-one str="" data="data" fun="fun()"></div>
</div>

app.directive('directiveOne', function () {
    return {
        restrict: 'A',
        template: '<div>@:</div><div>=:</div><div ng-click="fun()">fun</div>',
        scope:{
            str:'@str',
            data:'=data',
            fun:'&fun'
        }
    };
});

结果

@:controller定义的内容
=:controller定义的内容
fun

控制台(点击fun
this is a function
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页