Angular 指令

什么是指令

Angular通过被称为指令的属性来扩展HTML
AngularJS 通过内置的指令来为应用添加功能。
AngularJS 允许你自定义指令。

指令长成啥样

ng-开头,比如ng-appng-bind

<!DOCTYPE html>
<html lang="en" ng-app>

<body>
    <div ng-init="firstName = 'John'">
        <p>firstName:<span ng-bind='firstName'></span></p>
    </div>
</body> 
<script src='../angular.min.js'></script>

</html>

运行结果

常用的指令

ng-app是告诉HTML,这个DOM用Angular写的,如果移除ng-app,就无法识别Angular运算,
ng-init指令初始化程序数据,
ng-model把定义的数据绑定到程序,绑定之后就可以在HTML中使用表达式{{}}取值

<div ng-app="" ng-init="quantity=1;price=5">
 
<h2>价格计算器</h2>
 
数量: <input type="number"    ng-model="quantity">
价格: <input type="number" ng-model="price">
 
<p><b>总价:</b> {{ quantity * price }}</p>
 
</div>

ng-repeat重复HTML元素,类似for in循环

<div ng-app="" ng-init="names=['Jani','Hege','Kai']">
  <p>使用 ng-repeat 来循环数组</p>
  <ul>
    <li ng-repeat="x in names">
      {{ x }}
    </li>
  </ul>
</div>

AngularJS 完美支持数据库的 CRUD(增加Create、读取Read、更新Update、删除Delete)应用程序。
把实例中的对象想象成数据库中的记录。

完整的指令内容可以参阅 AngularJS 参考手册

自定义指令

有点像vue里面的自定义组件
使用.directive来添加自定义的指令,定义时使用驼峰命名法,如myDirective,使用时使用-分割,如my-directive

最佳实践:为了避免与将来的某些标准发生冲突,最好在自己的指令名称前加上前缀。例如,如果您创建了一个指令,那么HTML7引入相同的元素将是有问题的。两个或三个字母前缀(例如btfCarousel)效果很好。同样,请勿在自己的指令前加上前缀,ng否则它们可能与AngularJS的未来版本中包含的指令冲突。

模板扩展指令

假设您有一块代表客户信息的模板。此模板在您的代码中重复了很多次。当您在一个地方更改它时,您必须在其他几个地方更改它。这是使用指令简化模板的好机会。

<!DOCTYPE html>
<html lang="en">
<script src="../angular.min.js"></script>

<body ng-app="myApp">

    <div style="background-color: red">
        使用元素名调用指令
        <my-directive></my-directive>
    </div>
    <div style="background-color: yellow">
        使用属性调用指令
        <div my-directive></div>
    </div>
    <div style="background-color: blue">
        使用类调用指令
        <div class='my-directive'></div>
        <strong>必须设置restrict的值为'C'才能通过类名来调用指令</strong>
    </div>
    <div style="background-color: green">
        使用注释调用指令
        <!-- directive: my-directive -->
        <p><strong>注意:</strong> 我们需要在该实例添加 <strong>replace</strong> 属性, 否则评论是不可见的。</p>

        <p><strong>注意:</strong> 你必须设置 <b>restrict</b> 的值为 "M" 才能通过注释来调用指令。</p>
    </div>

    <script>
        var app = angular.module("myApp", []);
        app.directive("myDirective", function () {
            return {
                // restrict: 'C',
                restrict: "M",
                replace: true,
                template: "<h1>自定义指令!</h1>"
            };
        });
    </script>

</body>

</html>
限制使用 restrict

restrict可以限制指令用特定的方式调用,有四种取值

  • E:以元素的方式出现
  • A:以属性的方式出现
  • C:以类的方式出现(用的比较少)
  • M:以注释的方式(用的少)

restrict的默认值为EA,即可以通过元素名和属性名来调用指令

replace

替换,默认为false,如果设置为true的话,template中的内容会替换注释<!-- directive: my-directive -->的内容

注意,这种情况下,没有包裹的根元素,h1 和 p是同级元素的情况下,使用 replace:true 会报错,所以,指令模板必须要有一个根元素包裹

app.directive("myDirective", function () {
            return {
                replace: true,
                template: "<h1>自定义指令!</h1><p>啦啦啦啦啦</p>"
            };
        });

指令的隔离作用域

index.html

<div ng-controller="customCtrl">
    <my-customer info="naomi"></my-customer><hr>
    <my-customer info="igor"></my-customer><hr>
</div>

my-custom.html

Name:{{customerInfo.name}} Address:{{customerInfo.address}}

script.js

var app = angular.module('myApp',[])
app.controller('customCtrl',['$scope',function ($scope) {
    $scope.naomi = {name:'naomo',address:'ko ko da yo'}
    $scope.igor = {name:'igor',address:'a no hi'}
}])

app.directive('myCustomer',function () {
    return{
        restrict:'E',
        scope:{
            customerInfo : '=info'
        },
        templateUrl : 'my-custom.html'
    }
})

镜头拉到scope这一块

//...
scope: {
  customerInfo: '=info'
},
//...

scope选项是一个对象:它包含一组绑定的属性用于隔离作用域间的绑定.在这个例子中仅仅只有一个属性

  • 它的名字(customerInfo)与指令的隔离作用域中属性customerInfo一致
  • 它的值(=info)告诉$compile去绑定info属性

注意: 这个在指令scope选项中的=attr属性的命名规则和指令的命名方式一样,为了绑定属性

,你需要这样声明=bindToThis.

如果你想要绑定的属性名和指令内部的变量名一样的话,你可以采取下面缩写的形式:

...
scope: {
  // same as '=customer'
  customer: '='
},
...

创建一个操作DOM的指令

在这个例子中我们会创建一个展示当前时间的指令.每过一秒,它会更新DOM来展示当前时间

指令如果想要操作DOM,一般是使用link选项来注册DOM监听器同时更新DOM,它在模板被复制以后执行,并且指令的具体逻辑代码会放在这里.
link接收一个函数如下所示
function link(scope, element, attrs, controller, transcludeFn):

  • scope是Angular 的scope对象
  • element是指令匹配到的用jqLite包裹了以后的元素
  • attrs是一个标准化属性名的key-value对象.通过它可以访问到指令上的全部属性
  • controller表示指令自己的控制器或指令引入的控制器实例(如果有的话).确切值依赖于指令的require选项
  • transcludeFn 是预先绑定到正确包含范围的包含链接功能
<div ng-controller="Controller">
    Date format: <input ng-model="format"> <hr/>
    Current time is: <span my-current-time="format"></span>
</div>
var app = angular.module('docsTimeDirective',[])
app.controller('Controller',['$scope',function ($scope) {
        $scope.format = 'M/d/yy h:mm:ss a'
}])

app.directive('myCurrentTime',['$interval','dateFilter',function ($interval,dateFilter) {
    function link(scope,element,attrs) {
        var format , timeoutId;
        function updateTime() {
            element.text(dateFilter(new Date(),format))
        }
        scope.$watch(attrs.myCurrentTime,function (value) {
            format = value;
            updateTime();
        })
        element.on('$destroy',function () {
            $interval.cancel(timeoutId)
        })
        timeoutId = $interval(function () {
            updateTime();
        },1000)
    }
    return {
        link : link
    }
}])

这里有不少事情需要注意下.就像module.controllerAPI,这里的函数参数同样是被依赖注入的,因为这个,我们能够在link函数中使用 i n t e r v a l 和 d a t a F i l t e r 我 们 注 册 了 一 个 e v e n t 事 件 e l e m e n t . o n ( ′ interval和dataFilter 我们注册了一个event事件element.on(' intervaldataFiltereventelement.on(destroy’, …),什么时候会触发这个$destroy事件呢?

在AngularJS的事件冒泡机制中有一些特别的时刻,当被Angular的编译器编译过的DOM节点被销毁时,它会冒泡一个 d e s t r o y 事 件 ; 相 似 的 , 当 一 个 A n g u l a r J S 的 作 用 域 被 销 毁 时 , 它 会 向 那 些 监 听 的 作 用 域 广 播 一 个 destroy事件;相似的,当一个AngularJS的作用域被销毁时,它会向那些监听的作用域广播一个 destroy;,AngularJS,广destroy事件

通过监听这个事件,你能够移除可能会导致内存泄漏的事件监听器.scope上注册的监听器和元素当它们被销毁时会被自动清除.但如果你是在service,或者是还未被删除的DOM节点上注册了一个监听器,你不得不自己手动销毁它们,否则会有内存泄漏的风险

最佳实践: 你应该在指令的自动销毁机制之外手动地进行销毁.你能够使用element.on('$destroy', ...)或者是scope.$on('$destroy', ...)来当指令被移除时执行清除函数

创建一个包裹了其他元素的指令

我们已经见到:你能过通过使用隔离作用域来给指令传递一些数据;但有时比起字符串或者对象,我们更想要能够传递整个模板;让我们创建一个对话框组件,这个组件应该能包裹任意内容
为了这个目的,我们使用transclude选项.

<div ng-controller="customCtrl">
    <my-customer info="naomi"></my-customer><hr>
    <my-customer info="igor"></my-customer><hr>
</div>
app.directive('myCustomer',function () {
    return{
        restrict:'E',
        scope:{
            customerInfo : '=info'
        },
        templateUrl : 'my-custom.html'
    }
})
Name:{{customerInfo.name}} Address:{{customerInfo.address}}

参考

https://blog.csdn.net/weixin_34273479/article/details/88829286
https://www.jianshu.com/p/b37e16de6126

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值