大家好,我是IT修真院郑州分院,一枚正直、纯洁、善良的web程序员。
今天给大家分享一下,修真院官网 js任务中可能会使用到的知识点:
如何理解angularJS自定义指令directive中的scope
一、背景介绍
指令定义
AngularJS与JQuery最大的区别表现在数据双向绑定,实质就是DOM的操作形式不一样。 JQuery通过选择器找到DOM元素,再赋予元素的行为; 而AngularJS则是,将指令与DOM绑定在一起,再扩展指令的行为。 例如, ng-click 可以让一个元素能够监听 click 事件,并在接收到事件的时候执行AngularJS表 达式。 我们可以自己创造新的指令。使用angular的directive( )这个模块是用来定义指令的。
二、知识剖析
一个完整的自定义指令所包含的内容
angular.module(...);
.directive('My-directive', function(injectables) {
restrict: 'A',
priority: 0,
template: '',
templateUrl: 'directive.html',
replace: false,
transclude: false,
scope: false,
compile: function(tElement, tAttrs, transclude) {
return {
pre:functionpreLink(scope, iElement, iAttrs, controller) { ... },
post:functionpostLink(scope, iElement, iAttrs, controller) { ... }
}
},
link: function(scope, iElement, iAttrs) { ... }
});
restrict(字符串)
restrict 是一个可选的参数。它告诉AngularJS这个指令在DOM中可以何种形式被声明。默 认AngularJS认为 restrict 的值是 A ,即以属性的形式来进行声明。
restrict 值可以是以下几种:
E 作为元素名使用
A 作为属性使用
C 作为类名使用
M 作为注释使用
template (字符串或函数)
template 参数是可选的,必须被设置为以下两种形式之一:
一段HTML文本;
一个可以接受两个参数的函数,参数为 tElement 和 tAttrs ,并返回一个代表模板的字符 串。
templateUrl,引入外部的一个html文件
指令中的SCOPE
directive 默认能共享父 scope 中定义的属性,例如在模版中直接使用父 scope 中的对象和属性。 通常使用这种直接共享的方式可以实现一些简单的 directive 功能。但是当要创建一个可以重复使用的 directive的时候, 就不能依赖于父scope了,因为在不同的地方使用directive对应的父scope不一样。 所以需要一个隔离的scope。
scope属性的3种取值
①、false(默认值):直接使用父scope。
②、true:继承父scope
③、对象{ }:创建一个新的“隔离”scope,但仍可与父scope通信。隔离的scope,通常用于创建可复用的指令,也就是它不用管父scope中的model。然而虽然说是“隔离”,但通常我们还是需要让这个子scope跟父scope中的变量进行绑定。绑定的策略有3种:@、=、&。
三、常见问题
scope属性的3种取值对指令有什么影响?
四、解决方案
当scope参数被设置为false时有什么情况发生在这种情况下,在指令模板中可以直接使用父作用域中的变量,函数
angular.module("app",[])
//测试true和false
.controller("MyCtrl",function($scope){
$scope.userName="山水";
})
.directive("hello",function () {
return{
restrict:"AECM",
replace:true,
scope:false }
})
因为我们将scope的属性设置为false所以,我们创建的指令继承了父作用域的一切属性和方法,这也使得在指令的模板中我们可以使用这些属性和方法。
当我们将scope设置为true的时候,我们就新创建了一个作用域,只不过这个作用域是继承了我们的父作用域;我觉得可以这样理解,我们新创建的作用域是一个新的作用域,只不过在初始化的时候,用了父作用域的属性和方法去填充我们这个新的作用域。它和父作用域不是同一个作用域。
当我们将scope设置为false的时候,我们创建的指令和父作用域(其实是同一个作用域)共享同一个model模型,所以在指令中修改模型数据,它会反映到父作用域的模型中。
下面我们来看看如何使用这些前缀标识符:
1.@:单向绑定,外部scope能够影响内部scope,但反过来不成立;
这是一个单项绑定的前缀标识符。使用方法:在元素中使用属性
注意,属性的名字要用-将两个单词连接,因为是数据的单项绑定所以要通过使用{{}}来绑定数据。
2、=:双向绑定,外部scope和内部scope的model能够相互改变;
这是一个双向数据绑定前缀标识符。使用方法:在元素中使用属性,好比这样
注意,数据的双向绑定要通过=前缀标识符实现,所以不可以使用{{}}。
3、&:把内部scope的函数的返回值和外部scope的任何属性绑定起来。
这是一个绑定函数方法的前缀标识符。使用方法:在元素中使用属性,好比这样
注意,属性的名字要用-将多个个单词连接。
五、编码实战
六、扩展思考
我们的指令是如何利用这些前缀标识符来寻找我们想要的属性或者函数的?
@ 当指令编译到模板的name时,就会到scope中寻找是否含有name的键值对,如果存在,就像上面那样,看到@就知道这是一个单向的数据绑定,然后寻找原来的那个使用指令的元素上(或者是指令元素本身)含有这个值的属性即my-name={{name}},然后在父作用域查找{{name}}的值,得到之后传递给模板中的name。
=和&与@差不多,只不过=进行的是双向的数据绑定,不论模板还是父作用域上的属性的值发生改变都会使另一个值发生改变,而&是绑定函数而已。
七、参考文献
参考一:AngularJS 自定义指令
参考二:一招制敌 - 玩转 AngularJS 指令的 Scope (作用域)
八、更多讨论
1、directive有什么用
答:一般用于独立Dom元素的封装,应用场合为控件重用和逻辑模块分离,主要提高代码的可复用性
2、自定义指令中的各个参数有什么作用?
答:看上面参考文献AngularJS 自定义指令,里面有各个参数的详解
3、如何理解指令中的 controller, complile , link函数
答:AngularJs 的生命周期;分为两个阶段:
第一个阶段是编译阶段: 在编译阶段,AngularJS会遍历整个HTML文档并根据JavaScript中的指令定义来处理页面上声明的指令。 每一个指令的模板中都可能含 有另外一个指令,另外一个指令也可能会有自己的模板。当AngularJS调用HTML文档根部的指令时, 会遍历其中所有的模板,模板中也可能包 含带有模板的指令.一旦对指令和其中的子模板进行遍历或编译, 编译后的模板会返回一个叫做模板函数的函数。我们有机会在指令的模板函 数被返回前,对编译后的DOM树进行修改。
第二个阶段是链接阶段:链接函数来将模板与作用域链接起来;负责设置事件监听器,监视数据变化和实时的操作DOM.链接函数是可选的。 如果定义了编译函数,它会返回链接函数,因此当两个函数都定义了时,编译函数会重载链接函数 指令的控制器和link函数可以进行互换。控制器主要是用来提供可在指令间复用的行为,但链接函数只能在当前内部指令中定义行为, 且无法在指令间复用.link函数可以将指令互相隔离开来,而controller则定义可复用的行为。
八、
PPT链接:PPT
视频链接:
今天的分享就到这里啦,欢迎大家点赞、转发、留言、拍砖~