指令(directive)是angular里面最核心也是最难懂的东西,在慕课网看了下大漠穷秋老湿的视频,本身百度半天作了一些小test,总算把一切都搞明白了。html
先列出学习来源:angularjs
指令中controller和link的区别:http://www.cnblogs.com/CreateMyself/p/5568202.htmlbootstrap
angular视频教程:http://www.imooc.com/learn/156app
指令中的隔离 Scope :https://blog.coding.net/blog/angularjs-directive-isolate-scope框架
angular学习笔记:https://www.zouyesheng.com/angular.html#toc68dom
首先你得先建立一个module:ionic
var module1 = angular.module('module1',[]);
angular.bootstrap(document.body,['module1']);
而后你还得有一个对应的controller:函数
var module1 = angular.module('module1',[]); module1.controller('ctl1', function($scope) { $scope.content = 'i\'m, module 1'; $scope.name = 'module1'; $scope.save = function() { console.log('is function save'); }; });
angular.bootstrap(document.body,['module1']);
而后你就能够安心的建立指令了:学习
// 衔接上面的代码
m1.directive('testDirective', function() { // 将对象return出去 return{ restrict: 'E',// 指令类型 E:element A:attribute M:comment C: class template: '<div>我是指令生成的内容</div>'; replace: true, //使用模板替换原始标记 指令内本来的数据将被清空 } });
angular.bootstrap(document.body,['module1']);
对应的html能够这样写:ui
<body> <div ng-controller="ctl1">{{content}} <test-directive>这是本来的内容</test-directive> </div> </body>
以上代码须要注意一下几点:
1.咱们定义的指令名称是testDirective,可是在html中要写成test-directive。
2.咱们把指令里面的代码都放在了function中的return里面,其实return出去的内容就是整个指令对象。
3.angular.bootstrap(document.body,['module1']);至关于咱们在html中使用ng-app指令。推荐使用bootstarp而不是ng-app;
指令的属性以下:
其中的name、priority、terminal不作详细的介绍。
name就是指令名,对应上面代码中的testDirective,priority多个指令设置在同一个元素上的执行优先级,执行顺序从低至高:1>2>3.priority的值为正整数,好比priority: 1,
terminal, true/false 若是为true,同一个元素上的其余指令的优先级高于本指令,其余指令将中止执行
angular内置的一些指令,好比ng-app,ng-click之类的,都是以html元素的属性(atrrbile)的形式来实现的,我在使用ionic框架的时候,里面有不少自定义的标签、好比:<ion-content>
</ion-content>。这也是一个指令,他是经过html元素(element)来实现的。除了这两个以外,指令还支持class(html标签的class属性)、commment(html中的注释)来实现。
在JS代码中,restrict能够有如下赋值:
restrict: 'AE',// 指令类型 E:element A:attribute M:comment C: class
能够是多个restrict: 'AEMC',也能够是一个restrict: 'E'。在html中对应的写法为:
其中注释: <!-- 两边必定要留空格,否则什么都不会发生 -->
同一个指令中只能template和templateUrl只能选其一。
template为模板内容。即你要在指令所在的容器中插入的html代码。
template属性接收一个字符串,相似这样:
template: '<div>我是指令生成的内容</div>';
你也能够将整个template写得很复杂,可是,复杂的代码很是不易维护。而且你还得换行,得用字符串拼接每一行。
当你的tamplate超出10行就会显得辣眼睛,过长的template建议使用templateUrl代替。
templateUrl为从指定地址获取模板内容。即你要在指令所在的容器中插入的一个.html文件。
有了templateUrl咱们就能够将想实现的内容写成一个单独的html模版,在须要的地方插入,使用起来会很舒服。
这里的templateUrl相似于JSP中的include,angular也有一个ng-include指令。
具体的详细请点链接:http://www.ziqiangxuetang.com/angularjs/angularjs-include.html
replace:是否用模板替换当前元素。true : 将指令标签替换成temple中定义的内容,页面上不会再有<my-directive>
标签;false :则append(追加)在当前元素上,即模板的内容包在<my-directive>
标签内部。默认false。
transculde:是否使用ng-transculde来包含html中指令包含的原有的内容,接收两个参数true/false
先上例子:replace
var app = angular.module("app", []) .directive("hello", function () { var option = { restrict: "AECM", template: "<h3>Hello, Directive</h3>", replace: true //这里replace为true,因此原来的内容会被template代替 }; return option; })
<html> <head></head> <body> <hello>我是原来的内容</hello> ===> 变成<h3>Hello, Directive</h3>
若是replace为false ===><hello><h3>Hello, Directive</h3></hello>
</body>
</html>
transclude:
var app = angular.module("app", []) .directive("hello", function () { var option = { restrict: "AECM", template: "<h3>Hello, Directive</h3><span ng-transclude></span>", transculde: true //这里transculde为true,因此原来的内容会被放在有ng-transclude属性的标签内 }; return option; })
<html> <head></head> <body> <hello>我是原来的内容</hello> ===> 变成<hello><h3>Hello, Directive</h3><span ng-transclude>我是原来的内容</span></hello> </body> </html>
directive 默认能共享父 scope 中定义的属性,例如在模版中直接使用父 scope 中的对象和属性。一般使用这种直接共享的方式能够实现一些简单的 directive 功能。
可是,当你要建立一个能够重复使用的directive的时候,就不能依赖于父scope了,由于在不一样的地方使用directive对应的父scope不同。
因此你须要一个隔离的scope,咱们能够向下面这样来定义咱们的scope。
module1.directive("testDirective", function () {
return {
scope: {
value: '提莫队长正在待命!'
},
template: 'Say:{{value}}'
}
});
这样就很方便的将咱们directive的上下文scope给定义出来了,可是,若是我想将父scope中的属性传递给directive的scope怎么办呢?
directive 在使用隔离 scope 的时候,提供了三种方法同隔离以外的地方交互:
以上三种方式都要在directive的attr属性中进行赋值。上面的话理解起来比较困难,我根据本身的理解作了一下修改:
@:只能绑定字符串,因此一些简单的继承父scope的属性使用@
=: 须要实现双向数据绑定的时候使用=
&: 提供一种方式执行一个表达式在父scope的上下文中,即便用于将父scope中的函数绑定在指令的scope中
以上的理解也许有些偏颇,欢迎指正。
(1)先说@
app.controller("ctl1", function ($scope) { $scope.name = "hello world"; }).directive("testDirective", function () { return { scope: { name: "@" }, template: 'Say:{{name}} <br>改变隔离scope的name:<input type="buttom" value="" ng-model="name" class="ng-pristine ng-valid">' } })
<div ng-controller="ctl1"> <div> <div>父scope: <div>Say:{{name}}<br>改变父scope的name:<input type="text" value="" ng-model="name"/></div> </div> <div>隔离scope:这个显示为hello world <div test-directive name="{{name}}"></div> </div> <div>隔离scope(不使用{{name}}这个就直接显示为name了): <div test-directive name="name"></div> </div> </div>
咱们在test-directive指令所在的div上面,增长了一个name属性,要使用双花括号来给属性赋值。也能够写成nameCopy:'@nameForCtl',这样写,在给directive中的scope的属性赋值的时候,获取查询@后面的name这个标识对应的属性的值(这里nameForCtl在js中是驼峰写法,一样的在html中对应的属性名应该写成name-for-ctl)。不是很推荐这种写法,感受有点多余。
(2)=
上一个例子中,咱们使用name="{{name}}"的形式来传递父scope 的属性对应的值,so,咱们只是把对应的值传递给了directive的scope,当我想实如今directive中改变父scope传递过来的值时,父scope中的值也对应的改变,显然用@这种方法走不通。
这时=就派上用场了。
app.controller("ctl1", function ($scope) { $scope.user = { name: 'hello', id: 1 }; }).directive("testDirective", function () { return { scope: { user: "=" }, template: 'Say:{{user.name}} <br>改变隔离scope的name:<input type="buttom" value="" ng-model="user.name"/>' } })
<div ng-controller="ctl1"> <div>父scope: <div>Say:{{user.name}}<br>改变父scope的name:<input type="text" value="" ng-model="user.name"/></div> </div> <div>隔离scope: <div isolated-directive user="user"></div> </div> <div>隔离scope(使用{{name}},这个会报错): <div isolated-directive user="{{user}}"></div> </div> </div>
这一个例子和上一个例子不一样的地方就是属性赋值的时候,一个应该使用{{}},一个不应使用。=为了实现双向数据绑定,angular会使用‘=’对应的属性的值与父scope中的属性进行匹配,而后传递给diractive中的scope。至于实现的细节和原理,这里我就不说了(实际上是不大清楚)。
(3)&
& 方式提供一种途经使directive 能在父 scope 的上下文中执行一个表达式。此表达式能够是一个 function。其实说白了,就是可使用在父scope中定义的函数。
好比:当你写了一个 directive,当用户点击按钮时,directive 想要通知 controller,controller 没法知道 directive 中发生了什么,也许你能够经过使用 angular 中的 event 广播来作到,可是必需要在 controller 中增长一个事件监听方法。
最好的方法就是让 directive 能够经过一个父 scope 中的 function,当 directive 中有什么动做须要更新到父 scope 中的时候,能够在父 scope 上下文中执行一段代码或者一个函数。
app.controller("ctl1", function ($scope) { $scope.value = "hello world"; $scope.click = function () { $scope.value = Math.random(); }; }).directive("testDirective", function () { return { scope: { action: "&" }, template: '<input type="button" value="在directive中执行父scope定义的方法" ng-click="action()"/>' } })
<div ng-controller="ctl1"> <div>父scope: <div>Say:{{value}}</div> </div> <div>隔离scope: <div isolated-directive action="click()"></div> </div> </div>
在上面的例子中,咱们的属性action赋值为一个方法:action="click()",这样一写,一眼就看出来是个什么东西了,好像也没什么好解释的。
这三个涉及到指令的执行过程,本人暂时尚未比较彻底的理解,因此这里只能让你们去看别人写的博客了(原谅我太笨);
链接在顶部。嗯。 ↑点击返回顶部