频道栏目
首页 > 资讯 > JavaScript > 正文

Angularjs学习笔记(五)指令

17-11-30        来源:[db:作者]  
收藏   我要投稿

一、指令基础
当浏览器加载一个包含AngularJS应用的HTML时,我们只需要用内置指令ng-app启动AngularJS应用,并标记出应用的根节点,这个指令需要以属性的形式来使用,因此可以将它写到任何位置,但是写到的开始标签上是最常规的做法:

1.指令的使用方式


任何在这个根元素内部的指令只要能够访问作用域,就可以访问$rootScope。
2.自定义指令
通过AngularJS模块API中的.directive()方法,我们可以通过传入一个字符串和一个函数来注册一个新指令。其中字符串是这个指令的名字,指令名应该是驼峰命名风格的,函数应该返回
一个对象。directive()方法返回的对象中包含了用来定义和配置指令所需的方法和属性。

angular.module('myApp',[])
.directive('myDirective', function() {
return {
restrict: 'E',
template: '
Click me to go to Google' //为了尽快掌握简单的属性定义,我们只用了restrict和template两个设置项来定义指令
};
});

为了让AngularJS能够调用我们的指令,需要修改指令定义中的restrict设置。这个设置告、诉AngularJS在编译HTML时用哪种声明格式来匹配指令定义。我们可以指定一个或多个格式。可以以元素(E) 、属性(A) 、类(C)或注释(M)的格式来调用指令,建议用属性A(在已有的标签上添加功能)和元素(使用模板的时候)的方式来调用。
这里写图片描述

AngularJS在页面加载以及调用指令定义后生成的代码, AngularJS把生成后的代码提供给Chrome进行渲染。默认情况下, AngularJS将模板生成的HTML代码嵌套在自定义标签内部
这里写图片描述
向指令定义中添加一些新的设置:我们可以将自定义标签从生成的DOM中完全移除掉,
并只留下由模版生成的链接。将replace设置为true就可以实现这个效果:

angular.module('myApp', [])
.directive('myDirective', function() {
return {
restrict: 'E',
replace: true,
template: 'Click me to go to Google'
};
});

这里写图片描述
当AngularJS启动应用时,它会把第一个参数当作一个字符串,并以此字符串为名来注册第二个参数返回的对象。 AngularJS编译器会解析主HTML的DOM中的元素、属性、注释和CSS类名中使用了这个名字的地方,并在这些地方引用对应的指令。当它找到某个已知的指令时,就会在页面中插入指令所对应的DOM元素。

template参数是可选的,必须被设置为以下两种形式之一:
? 一段HTML文本;
? 一个可以接受两个参数的函数,参数为tElement和tAttrs,并返回一个代表模板的字符串。
如果模板字符串中含有多个DOM元素,或者只由一个单独的文本节点构成,那它必须被包含在一个父元素内。换句话说,必须存在一个根DOM元素:

template: '\
<-- single root element -->\ Click me\

When using two elements, wrap them in a parent element

\
\

另外,注意每一行末尾的反斜线,这样AngularJS才能正确解析多行字符串。

templateUrl是可选的参数,可以是以下类型:
? 一个代表外部HTML文件路径的字符串;
? 一个可以接受两个参数的函数,参数为tElement和tAttrs,并返回一个外部HTML文件路径的字符串。
默认情况下,调用指令时会在后台通过Ajax来请求HTML模板文件。有两件事情需要知道。
? 在本地开发时,需要在后台运行一个本地服务器,用以从文件系统加载HTML模板,否则会导致Cross Origin Request Script(CORS)错误。
? 模板加载是异步的,意味着编译和链接要暂停,等待模板加载完成。

我们自定义指令是为了复用,肯定会用在不同的controller里面。为了在不同的控制器里面使用自定义指令,需要为指令增加配置项attr,指令怎么根据配置项调用不同控制器的方法?见下第5条:link
3.向指令中传递数据
注意,我们在模板中硬编码了URL和链接文本:

template:' Click me to go to Google'

我们的目标是关注指令的公共接口,就像其他任何编程语言一样。实际上,应该将上面的模板转换成可以接受两个变量的形式:一个变量是URL,另一个是链接文本:
template: '{{ myLinkText }}'
在主HTML文档中,可以给指令添加myUrl和myLinkText两个属性,这两个参数会成为指令内部作用域的属性:


 

有好几种途径可以设置指令内部作用域中属性的值。最简单的方法就是使用由所属控制器提供的已经存在的作用域。如果控制器被移除,或者在控制器的作用域中也定义了一个叫myUrl的属性,AngularJS 允许通过创建新的子作用域或者隔离作用域来解决这个常见问题。


 
angular.module('myApp', [])
.directive('myDirective', function() {
    return {
        restrict: 'A',
        replace: true,

        scope: {
            myUrl: '@', //绑定策略
            myLinkText: '@' //绑定策略
        },

        template: '' +'{{myLinkText}}'
    };
});

4.缓存
在模板第一次被引用时,它会被载入到模板缓存中以便快速的检索。angular直接通过 $templateCache 服务
这里写图片描述
5.link 方法:
回顾:
directive中的几个属性:
restrict
E: 表示该directive仅能以element方式使用,即:
A: 表示该directive仅能以attribute方式使用,即:

 

EA: 表示该directive既能以element方式使用,也能以attribute方式使用
transclude
directive可能接受页面上的其他html内容时才会用到,建议先去掉该参数。有些高阶了。
scope
写上该属性时,就表示这个directive不会从它的controller里继承$scope对象,而是会重新创建一个。
templateUrl
你的directive里的html内容
link
可以简单理解为,当directive被angular 编译后,执行该方法,是用来处理指令内部事务的,包括:给元素绑定事件/数据之类的。

 

compile在编译前执行,负责把template(包括transclude所引用的)变成一个完整的DOM结构。 link在编译后执行,
负责根据controller和scope里的东东,给compile得到的DOM注册事件、关联数据,或者repeat之。

link里面有三个参数:
第一个参数scope基本上就是上面写的那个scope。
element简单说就是$(‘my-dialog’)
attrs是个map,内容是你这个directive上的所有属性,
require 之后,link就会多一个参数(第四个参数,scope,element,attrs,superCon
这里写图片描述
当有两种加载方式时,可以给自定义指令增加属性:
这里写图片描述
指令内部怎么获取到哪种加载方式呢?attr!直接写属性小写名,不要加括号
这里写图片描述

那什么时候把逻辑写在controller里,什么时候写在link里呢?
如果想让方法暴露出结果,在外部被调用,则写在controller里
link是处理指令内部的事物的,比如给元素绑定事件、数据
6.指令间的交互
通过require以及link第四个参数superCon:

var myModule = angular.module("MyModule", []);
myModule.directive("superman", function() {
    return {
        scope: {},  //创建独立作用域
        restrict: 'AE',
        controller: function($scope) {
            $scope.abilities = [];
            this.addStrength = function() {
                $scope.abilities.push("strength");
            };
            this.addSpeed = function() {
                $scope.abilities.push("speed");
            };
            this.addLight = function() {
                $scope.abilities.push("light");
            };
        },
        link: function(scope, element, attrs) {
            element.addClass('btn btn-primary');
            element.bind("mouseenter", function() {
                console.log(scope.abilities);
            });
        }
    }
});
myModule.directive("strength", function() {
    return {
        require: '^superman',//把supermanCtrl自动注入到指令中,就可以调用superman控制器中的方法了
        link: function(scope, element, attrs, supermanCtrl) {   
            supermanCtrl.addStrength();
        }
    }
});
myModule.directive("speed", function() {
    return {
        require: '^superman',
        link: function(scope, element, attrs, supermanCtrl) {
            supermanCtrl.addSpeed();
        }
    }
});
myModule.directive("light", function() {
    return {
        require: '^superman',
        link: function(scope, element, attrs, supermanCtrl) {
            supermanCtrl.addLight();
        }
    }
});

页面代码:


动感超人---力量
动感超人2---力量+敏捷
动感超人3---力量+敏捷+发光

7、创建独立scope
为了使指令相互独立使用,我们应该在return里面创建独立scope:

myModule.directive("superman", function() {
    return {
        scope: {},  //创建独立作用域
        restrict: 'AE',
        controller: function($scope) {
        }
    }
});
相关TAG标签
上一篇:前端面试题汇总(一)
下一篇:微信小程序MINA视图层的代码
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站