资讯专栏INFORMATION COLUMN

Angularjs 开发指南 自定义指令(custom directives)

calx / 745人阅读

摘要:使用开发,很重要的一步是需要开发自定义的指令。接下来分几个步骤记录如何开发一个自定义的指令。对这个元素及其子元素进行变形之类的操作是安全的。链接函数链接函数负责注册事件和更新。说明和是指令的关键部分,留在下一章中详细讨论。

使用Angularjs开发,很重要的一步是需要开发自定义的指令(custom directives)。
接下来分几个步骤记录如何开发一个自定义的指令。

目录:

指令是什么?

写一个基本的指令

指令的属性说明

指令是什么

Angularjs中的指令,我个人的简单的理解:指令=控件
指令实际是对Html元素的扩展,传统的服务端控件,例如asp.net中的服务器端控件(处理在服务端,最终编译成html返回给客户端),其实也是对Html元素的扩展。angularjs中的指令,最终其实也是经过angularjs(其实就是javascript)的编译处理,最终输出成html。具体的细节不继续细说,如果对angularjs毫无认识的童鞋,建议了解一些基本概念以后再看。

写一个基本的指令
var simpleapp=angular.module("simpleapp");
simpleapp.directive("simpleDirective", function () {
    var directiveObj = {
        template:"

这是一个自定义指令

" } return directiveObj; });

    

以上就是一个简单的自定义指令,最终页面会输出指令里包含的内容。这里先不说属性,只先讨论应该在何处定义,下一节再说如何定义指令内部。

看上面示例,可以知道指令必须是在module下的,先得获取到模块对象simpleapp,然后使用directive函数来定义一个指令。

指令属性

在上节例子中可以看到,simpleapp.directive第二个参数最终执行后需要返回一个对象(我叫它指令对象),这个指令对象里面有可以包含很多属性,大概有12个,这节主要解释这些属性的用法。
我主要是按功能来给这些属性分类并讲解。

template和templateUrl都是用来指定指令模板的,模板是用来编译内容的一个基本模型。

template

字符串或函数,可以指定为一个html字符串,也可以是一个特定的函数。
例子:

template: "
" //or template:function(tElement, tAttrs) { return "..." },

当为一个函数时,函数应该返回一个字符串。函数的tElement, tAttrs分别代表一个元素和元素对应的属性集合。

templateUrl

字符串或函数,可以指定一个模板的地址,也可以是一个特定的函数。

templateUrl: "sometemplate.html"
//or
templateUrl:function(tElement, tAttrs) { return tAttrs.xx+"xx.html" },

当为一个函数时,函数应该返回一个字符串。函数的tElement, tAttrs分别代表一个元素和元素对应的属性集合。

restrict

字符串,这个属性用来限制指令匹配模式,可以有四种模式,分别是A(Attribute)、E(Element)、C(Class)、M(注释),这四种模式可以自由组合。

        
        

需要注意的是,如果不设置此属性,则默认匹配EA两种模式。

疑问:M的匹配方式是靠C控制的,即如果设置restrict:"C",实际匹配的是C和M,如果多带带设置restrict:"M"则无法生效。--这个问题不知道是为什么?

templateNamespace

主要是标记文档类型,可设置为html、svg、math。具体使用场景我也未曾使用过。
此处贴上官方说明:

 * String representing the document type used by the markup in the template.
 * AngularJS needs this information as those elements need to be created and cloned
 * in a special way when they are defined outside their usual containers like `` and ``.
 *
 * * `html` - All root nodes in the template are HTML. Root nodes may also be
 *   top-level elements such as `` or ``.
 * * `svg` - The root nodes in the template are SVG elements (excluding ``).
 * * `math` - The root nodes in the template are MathML elements (excluding ``).
 *
 * If no `templateNamespace` is specified, then the namespace is considered to be `html`.
priority

优先级,当一个DOM上有多个指令时,有会需要指定指令执行的顺序。 这个优先级就是用来在执行指令的compile函数前先排序的。高优先级的先执行。 相同优先级的指令顺序没有被指定谁先执行

transclude

个人认为这个属性还是比较难解释的,本身英文也不知怎么解释。我按个人理解叫做”局部替换“,这个属性通常是要和ng-transclude配合。
先说下官方的意思:

 * Extract the contents of the element where the directive appears and make it available to the directive.
 * The contents are compiled and provided to the directive as a **transclusion function**. See the
 * {@link $compile#transclusion Transclusion} section below.
 *
 * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the
 * directive"s element or the entire element:
 *
 * * `true` - transclude the content (i.e. the child nodes) of the directive"s element.
 * * `"element"` - transclude the whole of the directive"s element including any directives on this
 *   element that defined at a lower priority than this directive. When used, the `template`
 *   property is ignored.

个人理解是transclude开启时,在编译完成以后,会将编译后的内容放到ng-transclude指定的位置中,类似于占位符的作用。
我还是写一个例子,这样能够更直观的看出它是什么意思

//JS
simpleapp.directive("simpleTransclude", function () {
    return {
        template: "
这是模板原有的内容
", transclude: true }; }) //HTML 这是指令内容 //浏览器最终展现效果
这是模板原有的内容
这是指令内容
scope

作用域,如果声明了,则指令会产生一个私有的作用域,如果有多个,则只有一个新的会被创建,也就是最后一个。对更节点无效。而且这个作用域是孤立的,不会以原型继承的方式直接继承自父作用域。这是需要注意的地方。关于scope的内容需要将的太多,放在以后的文章中详细说(难道说其实我自己也搞不清?)。

controller

控制器的构造对象。这个控制器函数是在预编译阶段被执行的,并且它是共享的,其他指令可以通过它的名字得到(参考依赖属性[require attribute])。
注意它是在预编译的时候执行,这一点非常重要,这意味着你可以在预编译前,在这个controller中做一些你想做的事情。

controllerAs

AngularJS 1.2版本中提供了Controller As语法,简单说就是可以在Controller中使用this来替代$scope。其他与controller是一样的。

require

请求将另一个控制器作为参数传入到当前链接函数。 这个请求需要传递被请求指令的控制器的名字。如果没有找到,就会触发一个错误。请求的名字可以加上下面两个前缀:

? - 不要触发错误,这只是一个可选的请求。
^ - 没找到的话,在父元素的controller里面也查找有没有。

compile

编译函数,在时执行,且指执行一次。

function compile(tElement, tAttrs, transclude) { ... }

编译函数是用来处理需要修改模板DOM的情况的。因为大部分指令都不需要修改模板,所以这个函数也不常用。需要用到的例子有ngTrepeat,这个是需要修改模板的,还有ngView这个是需要异步载入内容的。编译函数接受以下参数。

tElement - template element - 指令所在的元素。对这个元素及其子元素进行变形之类的操作是安全的。

tAttrs - template attributes - 这个元素上所有指令声明的属性,这些属性都是在编译函数里共享的, 参考章节“属性”。

transclude - 一个嵌入的链接函数function(scope, cloneLinkingFn)。

注意:如果模板被克隆了,那么模版实例和链接实例可能不是同一个对象。 所以在编译函数不要进行任何DOM变形之外的操作。 更重要的,DOM监听事件的注册应该在链接函数中做,而不是编译函数中。

编译函数可以返回一个对象或者函数。

返回函数 - 等效于在编译函数不存在时,使用配置对象的link属性注册的链接函数。

返回对象 - 返回一个通过pre或post属性注册了函数的对象- 使你能更具体的链接函数的执行点。参考下面pre-linking和post-liking函数的解释。

link

链接函数

function link(scope, iElement, iAttrs, controller) { ... }

链接函数负责注册DOM事件和更新DOM。它是在模板被克隆之后执行的。 它也是大部分指令逻辑代码编写的地方。

scope - 指令需要监听的作用域。

iElement - instance element - 指令所在的元素。只有在postLink函数中对元素的子元素进行操作才是安全的,因为那时它们才已经全部连接好。

iAttrs - instance attributes - 实例属性,一个标准化的、所有声明在当前元素上的属性列表,这些属性在所有链接函数间是共享的。参考“属性”。

controller - 控制器实例,如果至少有一个指令定义了控制器,那么这个控制器就会被传递。控制器也是指令间共享的,指令可以用它来相互通信。

Pre-linking function 在子元素被链接前执行。不能用来进行DOM的变形,以为可能导致链接函数找不到正确的元素来链接。

Post-linking function 所有元素都被链接后执行。可以操作DOM的变形。

说明

link和compile是指令的关键部分,留在下一章中详细讨论。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/79382.html

相关文章

  • [译] 如何使用 TypeScript 编写定义 AngularJS 指令

    摘要:在这篇文章中,我将告诉你如何用编写自定义指令。中的自定义指令让我们来创建一个只为任何的块,小部件或者人名在右边添加标题,子标题和文本的指令。另外,设置了指令的使用级别给元素和属性,分别使用和表示。 原文链接 : How to write custom AngularJS Directive using TypeScript?原文作者 : Siddharth Pandey译者 : 李林璞...

    CloudwiseAPM 评论0 收藏0
  • 创建定义指令

    摘要:我们通常通过其区分大小写的规范化名称例如,来定义指令。在其目前的实现上,我们应该需要去创建一些不同点控制器用来重用这个指令。如此,绑定是理想的将回调函数绑定到指令行为。这被指令调用指明。前缀表示该指令在其父元素上搜索控制 文档翻译至angularjs.org. 文档解释了您何时想在AngularJS应用程序中创建自己的指令,以及如何实现它们。 | 建议搭配原文食用 | 什么是指令? 在...

    zzbo 评论0 收藏0
  • Angularjs 1 深度解析:组件化编程

    摘要:一个高度可复用的组件则可以被称为控件,是可以单独投稿项目库的。行为的定制化通过参数绑定实现组件行为的定制化。组件被销毁时调用。当有组件复用的情况时请使用标识指定接收对象模型另外最好给事件名添加组件前缀。 转自自己在开源中国的博客:https://my.oschina.net/u/7247... angular 1 也要面向组件编程 前端组件化是前端开发模式中一个不可逆转的趋势,三大主要...

    caohaoyu 评论0 收藏0
  • 高级 Vue 组件模式 (6)

    摘要:之后再引入该指令,如下之后就可以在组件的模板中使用该指令了,比如一切都将按预期中运行,当组件的状态为开时,组件的根元素会增加一个的内容增强属性。到后来兴起了组件化开发的开发思想,指令似乎是随着的没落而消失了踪影。 06 通过 directive 增强组件内容 目标 之前的五篇文章中,switch 组件一直是被视为内部组件存在的,细心的读者应该会发现,这个组件除了帮我们提供开关的交互以外...

    makeFoxPlay 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<