什么是指令
Angular通过被称为指令的属性来扩展HTML
AngularJS 通过内置的指令来为应用添加功能。
AngularJS 允许你自定义指令。
指令长成啥样
以ng-
开头,比如ng-app
、ng-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(' interval和dataFilter我们注册了一个event事件element.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