一指令定义
对于指令, 可以把它简单的理解成在特定 DOM 元素上运行的函数, 指令可以扩展这个元素的功能
首先来看个完整的参数示例再来详细的介绍各个参数的作用及用法:
- <div my-directive></div>
- angular.module('myApp', [])
- .directive('myDirective', function() {
- return {
- restrict: String,
- priority: Number,
- terminal: Boolean,
- template: String or Template Function:
- function(tElement, tAttrs) {...},
- templateUrl: String,
- replace: Boolean or String,
- scope: Boolean or Object,
- transclude: Boolean,
- controller: String or
- function(scope, element, attrs, transclude, otherInjectables) { ... },
- controllerAs: String,
- require: String,
- link: function(scope, iElement, iAttrs) { ... },
- compile: // 返回一个对象或连接函数, 如下所示:
- function(tElement, tAttrs, transclude) {
- return {
- pre: function(scope, iElement, iAttrs, controller) { ... },
- post: function(scope, iElement, iAttrs, controller) { ... }
- }
- return function postLink(...) { ... }
- }
- };
- });
二指令参数的作用和意义(这个地方只选常用的几种来讲一下)
restrict[string]
restrict 是一个可选的参数用于指定该指令在 DOM 中以何种形式被声明默认值是 A, 即以属性的形式来进行声明
可选值如下:
E(元素)
<my-directive></my-directive>
A(属性, 默认值)
<div my-directive></div>
C(类名)
<div class="my-directive:expression;"></div>
M(注释)
<--directive:my-directive expression-->
一般考虑到浏览器的兼容性, 强烈建议使用默认的属性就可以即即以属性的形式来进行声明最后一种方式建议在不要求逼格指数的时候千万不要用
replace[bool]
replace 是一个可选参数, 如果设置了这个参数, 值必须为 true, 因为默认值为 false 默认值意味着模板会被当作子元素插入到调用此指令的元素内部,
例如上面的示例默认值情况下, 生成的 html 代码如下:
<my-directive value="http://www.baidu.com" text="百度"><a href="http://www.baidu.com">百度</a></my-directive>
如果设置 replace=true
- <a href="http://www.baidu.com" value="http://www.baidu.com" text="百度">百度</a>
- templateUrl[string or function]
templateUrl 是可选的参数, 可以是以下类型:
一个代表外部 HTML 文件路径的字符串;
一个可以接受两个参数的函数, 参数为 tElement 和 tAttrs, 并返回一个外部 HTML 文件路径的字符串
无论哪种方式, 模板的 URL 都将通过 ng 内置的安全层, 特别是 $getTrustedResourceUrl, 这样可以保护模板不会被不信任的源加载 默认情况下, 调用指令时会在后台通过 Ajax 来请求 HTML 模板文件加载大量的模板将严重拖慢一个客户端应用的速度为了避免延迟, 可以在部署应用之前对 HTML 模板进行缓存
- angular.module('app',[])
- .directive('myDirective', function () {
- return {
- restrict: 'A',
- templateUrl: function (elem, attr) {
- return attr.value + ".html"; // 当然这里我们可以直接指定路径, 同时在模板中可以包含表达式
- }
- };
- })
- controller[string or function]
controller 参数可以是一个字符串或一个函数当设置为字符串时, 会以字符串的值为名字, 来查找注册在应用中的控制器的构造函数.
- angular.module('myApp', [])
- .directive('myDirective', function() {
- restrict: 'A',
- replace: true,
- templateUrl: 'test.html',
- controller: 'SomeController'
- })
可以在指令内部通过匿名构造函数的方式来定义一个内联的控制器
- angular.module('myApp',[])
- .directive('myDirective', function() {
- restrict: 'A',
- controller:
- function($scope, $element, $attrs, $transclude) {
- // 控制器逻辑放在这里
- }
- });
我们可以将任意可以被注入的 ng 服务注入到控制器中, 便可以在指令中使用它了控制器中也有一些特殊的服务可以被注入到指令当中这些服务有:
1. $scope
与指令元素相关联的当前作用域
2. $element
当前指令对应的元素
3. $attrs
由当前元素的属性组成的对象
<div id="aDiv"class="box"></div>
具有如下的属性对象:
- {
- id: "aDiv",
- class: "box"
- }
三指令作用域
scope 参数[bool or object]
scope 参数是可选的, 可以被设置为 true 或一个对象默认值是 false
html 代码
<div ng-controller='MainController' ng-init="myProperty='Hello World!'">
外部: {{ myProperty}}
- <input ng-model="myProperty" />
- <div my-directive></div>
- </div>
js 代码
- angular.module('myApp', [])
- .controller('MainController', function ($scope) {
- })
- .directive('myDirective', function () {
- return {
- restrict: 'A',
- scope:false,// 切换为{},true 测试
- priority: 100,
- template: '<div > 内部:{{ myProperty }}<input ng-model="myProperty"/></div>'
- };
- });
当我们改变 scope 的值我们会发现
false: 继承但不隔离
1. 当我们将 scope 设置为 false 的时候, 我们创建的指令和父作用域 (其实是同一个作用域) 共享同一个 model 模型, 所以在指令中修改模型数据, 它会反映到父作用域的模型中
true: 继承并隔离
2. 当我们将 scope 设置为 true 的时候, 我们就新创建了一个作用域, 只不过这个作用域是继承了我们的父作用域;
我觉得可以这样理解, 我们新创建的作用域是一个新的作用域, 只不过在初始化的时候, 用了父作用域的属性和方法去填充我们这个新的作用域它和父作用域不是同一个作用域
{}: 隔离且不继承
3. 当我们将 scope 设置为 {} 时, 意味着我们创建的一个新的与父作用域隔离的新的作用域, 这使我们在不知道外部环境的情况下, 就可以正常工作, 不依赖外部环境
四绑定策略
在使用独立作用域 scope 的时候, 一般有三种绑定传递策略, @单向传递字符串 = 双向传递 & 单向传递父级的方法
- <inputtype="text" ng-model="myUrl">
- <div my-directive my-url="{{myUrl}}" my-age="age" change-my-age="changeAge()></div>
- angular.module('myApp',[])
- .directive('myDirective',function(){
- return{
- restrict:'A',// 属性方式
- replace:true,
- scope:{
- myUrl:'@',//@绑定策略(默认绑定到 my-url 指令属性)
- myAge:'='//= 双向绑定(父子互相影响)
- changeMyAge:'&' // 传递父作用域的方法
- },
- template:'<a href=" {{myUrl}}
- "ng-click=changeMyAge()>{{ myAge }}</a>'
- }
- });
在上面的代码中, 我创建了一个指令 myDirective 该指令创建了两个变量 myUrlmyLinkText, 并且这俩个变量都是采用 @绑定策略
说一下, 不管是 @= 还是 & 绑定策略, 它们都有一个默认的方式, 以 @绑定策略为例, 如上面代码那么样: myUrl:'@', 直接用一个 @表示绑定的方式, 它就会默认得将指令属性 my-url 的值赋值给 myUrl 变量
当然, 你不想使用默认的方式, 也就是说, 你不想 myUrl 变量绑定 my-url 的值, 而想要绑定其它属性名的值, 那么你可以在 @后加上你希望的属性名(格式要求: 驼峰式)
如, 我想讲 myUrl 绑定到
<myDirective></myDirective>
指令的 some-attr 属性的值, 那么你可以这样写: myUrl:'@someAttr'
那么我们知道了指令的 myUrl 变量的值是如何来的, 那么我们要如何在 template 中使用它呢?
这个很简单, 看上面的代码就能很明白了, 我们在 template 中的代码中需要用表达式的方式对其引用{{myUrl}}, 这样我们就能够使用到 myUrl 变量的值了~
1. 本地作用域属性: 使用 @符号将本地作用域同 DOM 属性的值进行绑定, 使指令内部作用域可以使用外部作用域的变量:
@ 可以在指令中使用绑定的字符串了
2. 双向绑定: 通过 = 可以将本地作用域上的属性同父级作用域上的属性进行双向的数据绑定就像普通的数据绑定一样, 本地属性会反映出父数据模型中所发生的改变
3. 父级作用域绑定 通过 & 符号可以对父级作用域进行绑定, 以便在其中运行函数意味着对这个值进行设置时会生成一个指向父级作用域的包装函数
要使调用带有一个参数的父方法, 我们需要传递一个对象, 这个对象的键是参数的名称, 值是要传递给参数的内容
来源: https://www.cnblogs.com/chaixiaozhi/p/8467798.html