angularjs中directive指令与component组件有什么区别?

 壹 ❀ 引html

我在前面花了两篇博客分别系统化介绍了angularjs中的directive指令与component组件,固然directive也能实现组件这点毋庸置疑。在了解完二者后,即使咱们知道component就像删减版的directive,用法上大同小异,但二者在使用角度仍然存在很多差别,那么本文将详细对比二者,加深你们的认知,那么本文开始。angularjs

 贰 ❀ 区别详解数组

  Directive Component
bindings(用于父传值子)  NO  YES(绑定至控制器)
bindToController  YES  NO
compile function(编译函数)  YES  NO
controller  YES  YES
controllerAs  YES(默认flase)  YES(默认$ctrl)
link functions(连接函数)  YSE  NO
multiElement  YES  NO
priority(组件优先权)  YES  NO
replace  YES  NO
require  YES  YES
restrict  YES  NO(仅支持元素)
scope  YES(绑定至scope)  NO(做用域老是隔离)
template  YES  YES
templateNamespace  YES  NO
templateUrl  YES  NO
terminal(优先权低的组件是否执行)  YES  NO
transclude  YES(默认false)  YES(默认false)

这是一份包含了指令directive与组件component全属性的表格,谁有谁没有已标注,至于具体用法可阅读博主先前完成的两篇博客。如今来讲说二者表现不一样:函数

1.建立与使用方式不一样ui

在建立上,directive在指令名后是一个回调函数,函数内返回一个包含指令配置的对象,而component在组件名后紧接一个包含组件配置的对象。this

在使用上,directive支持EMAC,即元素注释属性与类名,而component仅支持元素,所以component没有restrict,terminal,replace此类属性。spa

<!-- 指令 -->
<!-- directive:directive-name -->
<directive-name></directive-name>
<div directive-name></div>
<div class="directive-name"></div>

<!-- 组件 -->
<component-name></component-name>
angular.module('myApp', [])
    .controller('myCtrl', function ($scope) {})
    .directive('directiveName', function () {
        return {
            //定义属性配置
        }
    })
    .component('componentName', {
        //定义属性配置
    });

2.模板使用不一样rest

指令directive在使用模板,不论是template或者templateUrl,都要求模板代码用一个根元素进行包裹,但component并无这个要求。code

angular.module('myApp', [])
    .controller('myCtrl', function ($scope) {})
    .directive('directiveName', function () {
        return {
            template: '<span>1</span><span>2<span>', //错误
            template: '<div><span>1</span><span>2<span></div>' //正确
        }
    })
    .component('componentName', {
        //定义属性配置
        template: '<span>1</span><span>2<span>', //不会报错
    });

3.父子传值表现不一样component

咱们知道指令directivescope传值directive绑在scope上,component绑在this上,因此component要使用钩子函数。固然directive可使用bindTocontroller让传值也绑定在this上。

咱们知道component自带隔离做用域,而directive是否隔离由scope属性决定,false不建立做用域,true建立做用域但不隔离,{}建立隔离做用域。

当拥有隔离做用域时,父子互不相关,因此子没法继承父做用域中的任何数据,component得使用bindings传值,而directive得使用scope:{}传值:

<div ng-controller="myCtrl as vm">
    <echo1 name="name" age="vm.age"></echo1>
    <echo2 name="name" age="vm.age"></echo2>
</div>
angular.module('myApp', [])
    .controller('myCtrl', function ($scope) {
        $scope.name = '听风是风';
        this.age = 26;
    })
    .directive('echo1', function () {
        return {
            restrict: 'AE',
            replace: true,
            scope: {
                name: '<',
                age: '<'
            },
            template: '<div>{{name}}{{age}}</div>',
            controller:function($scope) {
                console.log($scope,this)
            }
        }
    })
    .component('echo2', {
        bindings: {
            name: '<',
            age: '<'
        },
        template: '<div>{{$ctrl.name}}{{$ctrl.age}}</div>',
        controller:function($scope) {
            console.log($scope,this);
        }
    });

在这个例子中,咱们在父级控制器中分别在scope以及this上绑定了两条数据,并分别传递给指令echo1与组件echo2,能够看到在二者的模板中使用是有差别的,指令使用传递过来的数据更像$scope的写法,而组件更像构造器。

这是由于directive传值默认是绑定在scope上的,而component传值默认绑定在控制器上,咱们能够分别打印二者的scope与this,首先是directive:

能够看到数据传递过来是直接绑定在scope中的,因此用起来与绑在$scope上同样,再来看看component:

能够看到传递过来的数据不是绑定在scope上,而是组件的控制器上,因为咱们没有设置controllerAs,因此这里默承认以经过$ctrl访问。

别忘了directive有一个bindToController属性,做用就是将传递过来的值绑定在控制器上,咱们修改代码,为directive添加此bindToController:true,再次输出能够看到scope与this发生了变化。

    .directive('echo1', function () {
        return {
            restrict: 'AE',
            replace: true,
            scope: {
                name: '<',
                age: '<'
            },
            bindToController: true,
            controllerAs: 'ctrl',
            template: '<div>{{ctrl.name}}{{ctrl.age}}</div>',
            controller: function ($scope) {
                console.log($scope, this)
            }
        }
    })

或许你想问能绑定在scope上干吗要绑定在控制器上呢?别忘了directive与component都有一个require属性,经过此属性咱们能注入其它组价或指令的控制器,也就是说你能用其它指令中定义的属性方法,前提是这些属性方法得绑定在this上,来看个例子:

<div ng-controller="myCtrl as vm">
    <echo1>
        <echo2></echo2>
    </echo1>
</div>
angular.module('myApp', [])
    .controller('myCtrl', function ($scope) {})
    .directive('echo1', function () {
        return {
            restrict: 'AE',
            replace: true,
            controller: function ($scope) {
                $scope.gender = 'male';
                this.name = '听风是风';
                this.sayName = function(){
                    console.log(this.name);
                }
            }
        }
    })
    .component('echo2', {
        template: '<div><button ng-click="$ctrl.echoCtrl.sayName()">点我</button></div>',
        require:{
            echoCtrl:'?^echo1'
        },
        controller: function ($scope) {
            this.$onInit = function () {
                console.log(this.echoCtrl);
            }
        }
    });

我在指令echo1的controller中分别在scope以及this上绑定了一些属性,而后在组件echo2中经过require注入echo1的控制器,能够看到咱们能经过此作法复用已经定义过的属性方法。同时咱们打印注入的控制器,能够看到只有绑定在echo1 this上的属性,scope上的属性并无传递过来。

4.component的controller中通常结合钩子函数使用,directive不须要

不论是经过scope/bindings传递父做用域数据过来,仍是require注入其它指令组件控制器上的属性方法,在模板上直接使用都是没问题的,只是一个在scope上一个在控制器上的区别,前面也有例子展现。

但若是咱们要在directive和component的controller中操做传递过来的数据component得使用钩子函数中才能获取到,不然就是undefined,看个例子:

<div ng-controller="myCtrl">
    <echo1 person="person"></echo1>
    <echo2 person="person"></echo2>
</div>
angular.module('myApp', [])
    .controller('myCtrl', function ($scope) {
        $scope.person = {
            name: '听风是风',
            age: '26'
        }
    })
    .directive('echo1', function () {
        return {
            restrict: 'AE',
            replace: true,
            scope: {
                person: '<',
            },
            template: '<div>{{name}}</div>',
            controller: function ($scope) {
                //传递过来的person绑定在scope上
                $scope.name = $scope.person.name;
            }
        }
    })
    .component('echo2', {
        bindings: {
            person: '<',
        },
        template: '<div>{{name}}</div>',
        controller: function ($scope) {
            //只有在钩子函数中才能获取到
            this.$onInit = function (){
                //传递过来的person绑定在控制器上
                $scope.name = this.person.name
            }
        }
    });

这个例子中咱们传递过来的是一个对象,可是咱们只须要在视图上渲染对象中的一条属性,因此在controller中作了一次数据加工。directive直接加工没问题,可是component必须在钩子函数中才能取到this.person对象,你们能够尝试注释掉外面的$onInit方法看看区别,这点在使用component的controller处理传递过来的数据必定得注意。

5.require使用不一样

前面已经提到directive与component都能使用require注入其它指令组件的控制器,以达到使用控制器中的数据,不过directive与component在require使用上有一点点区别,看个例子:

<div ng-controller="myCtrl">
    <echo>
        <echo1></echo1>
        <echo2></echo2>
    </echo>
</div>
angular.module('myApp', [])
    .controller('myCtrl', function ($scope) {})
    .directive('echo', function () {
        return {
            restrict: 'AE',
            replace: true,
            controller: function ($scope) {
                this.name = '听风是风';
            }
        }
    })
    .directive('echo1', function () {
        return {
            restrict: 'AE',
            replace: true,
            require: '?^echo',
            template: '<div>{{name}}</div>',
            link: function (scope, ele, attrs, ctrls) {
                console.log(ctrls);
                scope.name = ctrls.name;
            }
        }
    })
    .component('echo2', {
        require: {
            echoCtrl: '?^echo'
        },
        template: '<div>{{name}}</div>',
        controller: function ($scope) {
            //只有在钩子函数中才能获取到
            this.$onInit = function () {
                console.log(this.echoCtrl);
                $scope.name = this.echoCtrl.name;
            }
        }
    });

 

在directive中require的值是一个字符串或者一个数组(注入多个时),而且注入的指令/组件控制器将成为link函数的第四个参数,注意是link函数不是controller。

而component的require值一直是个对象,被注入的指令/组件的控制器须要做为自定义key的value,在controller中经过this.key访问,注意,使用一样须要钩子函数。

 叁 ❀ 使用抉择

咱们在上文中介绍了directive与component使用时存在的部分差别,那么实际开发中该如何抉择呢,其实在angular官网就已经给出了答案。

在AngularJS中,组件是一种特殊的指令,它使用更简单的配置,在属性默认值和属性配置实用角度上component有更大的优点,例如require key-value形式相比directive的数组更便于使用,controllerAs自带了默认值等。

固然directive也有component没法取代的一面,当咱们须要在编译和预连接函数中执行操做时,或者同一元素拥有多个指令须要定义优先级时,directive会比component更强大,没有谁好谁坏,只是根据需求来决定。

 肆 ❀ 总

那么到这里,关于directive与component使用区别介绍完毕了,若是你们对于directive与component使用有疑惑,能够阅读博主这两篇文章:

angularjs 一篇文章看懂自定义指令directive

一篇文章看懂angularjs component组件

若对于本文介绍的知识点有所疑惑,欢迎留言,我会及时回复,那么到这里本文结束。

相关文章
相关标签/搜索