angularJS 指令实践

AngularJS 指令(Directives)实践指南(1)

2014-03-12 10:22 陈鑫伟 编译 伯乐在线 我要评论(0) 字号:T | T
一键收藏,随时查看,分享好友!

一个指令用来引入新的HTML语法。指令是DOM元素上的标记,使元素拥有特定的行为。举例来说,静态的HTML不知道如何来创建和展现一个日期选择器控件。让HTML能识别这个语法,我们需要使用指令。指令通过某种方法来创建一个能够支持日期选择的元素。我们会循序渐进地介绍这是如何实现的。

AD:WOT2014课程推荐:实战MSA:用开源软件搭建微服务系统

指令(Directives)是所有AngularJS应用最重要的部分。尽管AngularJS已经提供了非常丰富的指令,但还是经常需要创建应用特定的指令。这篇教程会为你讲述如何自定义指令,以及介绍如何在实际项目中使用。在这篇文章的最后(第二部分),我会指导你如何使用Angular指令来创建一个简单的记事本应用。

概述

一个指令用来引入新的HTML语法。指令是DOM元素上的标记,使元素拥有特定的行为。举例来说,静态的HTML不知道如何来创建和展现一个日期选择器控件。让HTML能识别这个语法,我们需要使用指令。指令通过某种方法来创建一个能够支持日期选择的元素。我们会循序渐进地介绍这是如何实现的。 如果你写过AngularJS的应用,那么你一定已经使用过指令,不管你有没有意识到。你肯定已经用过简单的指令,比如 ng-mode, ng-repeat, ng-show等。这些指令都赋予DOM元素特定的行为。例如,ng-repeat 重复特定的元素,ng-show 有条件地显示一个元素。如果你想让一个元素支持拖拽,你也需要创建一个指令来实现它。指令背后基本的想法很简单。它通过对元素绑定事件监听或者改变DOM而使HTML拥有真实的交互性。

jQuery视角

想象一下使用jQuery如何创建一个日期选择器。首先,我们在HTML中添加一个普通的输入框,然后通过jQuery调用 $(element).dataPicker() 来将它转变成一个日期选择器。但是,仔细想一下。当一个设计人员过来检查HTML标记的时候,他/她能否立刻猜到这个字段实际上表示的内容?这只是一个简单的输入框,或者一个日期选择器?你需要查看jQuery代码来确定这些。而Angular的方法是使用一个指令来扩展HTML。所以,一个日期选择器的指令可以是下面的形式:

  1. <input type="text" /> 

或者是这样:

  1. <input type="text" /> 

这种创建UI组建的方式更加直接和清晰。你可以轻易地通过查看元素就明白这到底是什么。

创建自定义指令:

一个Angular指令可以有以下的四种表现形式: 1. 一个新的HTML元素(<data-picker></data-picker>) 2. 元素的属性(<input type=”text” data-picker/>) 3. CSS class(<input type=”text” class=”data-picker”/>) 4. 注释(<!–directive:data-picker –>) 当然,我们可以控制我们的指令在HTML中的表现形式。下面我们来看一下AngularJS中的一个典型的指令的写法。指令注册的方式与 controller 一样,但是它返回的是一个拥有指令配置属性的简单对象(指令定义对象) 。下面的代码是一个简单的 Hello World 指令。

  1. var app = angular.module('myapp', []);  
  2.    
  3. app.directive('helloWorld'function() {  
  4.   return {  
  5.       restrict: 'AE',  
  6.       replace: 'true',  
  7.       template: '<h3>Hello World!!</h3>' 
  8.   };  
  9. });  

在上面的代码中,app.directive()方法在模块中注册了一个新的指令。这个方法的第一个参数是这个指令的名字。第二个参数是一个返回指令定义对象的函数。如果你的指令依赖于其他的对象或者服务,比如 $rootScope, $http, 或者$compile,他们可以在这个时间被注入。这个指令在HTML中以一个元素使用,如下:

  1. <hello-world/>  
  2. //OR  
  3. <hello:world/>  

或者,以一个属性的方式使用:

  1. <div hello-world></div>  
  2. //OR  
  3. <div hello:world/>  

如果你想要符合HTML5的规范,你可以在元素前面添加 x- 或者 data-的前缀。所以下面的标记也会匹配 helloWorld 指令:

  1. <div data-hello-world></div>  
  2. //OR  
  3. <div x-hello-world></div>  

注意: 在匹配指令的时候,Angular会在元素或者属性的名字中剔除 x- 或者 data- 前缀。 然后将 – 或者 : 连接的字符串转换成驼峰(camelCase)表现形式,然后再与注册过的指令进行匹配。这是为什么,我们在HTML中以 hello-world 的方式使用 helloWorld 指令。其实,这跟HTML对标签和属性不区分大小写有关。 尽管上面的指令仅仅实现了静态文字的显示,但是这里还是有一些有趣的点值得我们去挖掘。我们在指令定义过程中使用了三个属性来配置指令。我们来一一介绍他们的作用。

  • restrict – 这个属性用来指定指令在HTML中如何使用(还记得之前说的,指令的四种表示方式吗)。在上面的例子中,我们使用了 ‘AE’。所以这个指令可以被当作新的HTML元素或者属性来使用。如果要允许指令被当作class来使用,我们将 restrict 设置成 ‘AEC’。
  • template – 这个属性规定了指令被Angular编译和链接(link)后生成的HTML标记。这个属性值不一定要是简单的字符串。template 可以非常复杂,而且经常包含其他的指令,以及表达式({{ }})等。更多的情况下你可能会见到 templateUrl, 而不是 template。所以,理想情况下,你应该将模板放到一个特定的HTML文件中,然后将 templateUrl 属性指向它。
  • replace – 这个属性指明生成的HTML内容是否会替换掉定义此指令的HTML元素。在我们的例子中,我们用 <hello-world></hello-world>的方式使用我们的指令,并且将 replace 设置成 true。所以,在指令被编译之后,生成的模板内容替换掉了 <hello-world></hello-world>。最终的输出是 <h3>Hello World!!</h3>。如果你将 replace 设置成 false,也就是默认值,那么生成的模板会被插入到定义指令的元素中。

打开这个 plunker,在”Hello World!!”右键检查元素内容,来更形象地明白这些。

Link函数和Scope

指令生成出的模板其实没有太多意义,除非它在特定的scope下编译。默认情况下,指令并不会创建新的子scope。更多的,它使用父scope。也就是说,如果指令存在于一个controller下,它就会使用这个controller的scope。 如何运用scope,我们要用到一个叫做 link 的函数。它由指令定义对象中的link属性配置。让我们来改变一下我们的 helloWorld 指令,当用户在一个输入框中输入一种颜色的名称时,Hello World 文字的背景色自动发生变化。同时,当用户在 Hello World 文字上点击时,背景色变回白色。 相应的HTML标记如下:

  1. <body ng-controller="MainCtrl">  
  2.   <input type="text" ng-model="color" placeholder="Enter a color" />  
  3.   <hello-world/>  
  4. </body>  

修改后的 helloWorld 指令如下:

  1. app.directive('helloWorld'function() {  
  2.   return {  
  3.     restrict: 'AE',  
  4.     replace: true,  
  5.     template: '<p style="background-color:{{color}}">Hello World',  
  6.     link: function(scope, elem, attrs) {  
  7.       elem.bind('click'function() {  
  8.         elem.css('background-color''white');  
  9.         scope.$apply(function() {  
  10.           scope.color = "white";  
  11.         });  
  12.       });  
  13.       elem.bind('mouseover'function() {  
  14.         elem.css('cursor''pointer');  
  15.       });  
  16.     }  
  17.   };  
  18. });  

我们注意到指令定义中的 link 函数。 它有三个参数:

  • scope – 指令的scope。在我们的例子中,指令的scope就是父controller的scope。
  • elem – 指令的jQLite(jQuery的子集)包装DOM元素。如果你在引入AngularJS之前引入了jQuery,那么这个元素就是jQuery元素,而不是jQLite元素。由于这个元素已经被jQuery/jQLite包装了,所以我们就在进行DOM操作的时候就不需要再使用 $()来进行包装。
  • attr – 一个包含了指令所在元素的属性的标准化的参数对象。举个例子,你给一个HTML元素添加了一些属性:,那么可以在 link 函数中通过 attrs.someAttribute 来使用它。

link函数主要用来为DOM元素添加事件监听、监视模型属性变化、以及更新DOM。在上面的指令代码片段中,我们添加了两个事件, click,和 mouseover。click 处理函数用来重置 <p> 的背景色,而 mouseover 处理函数改变鼠标为 pointer。在模板中有一个表达式 {{color}},当父scope中的 color 发生变化时,它用来改变 Hello World 文字的背景色。 这个 plunker 演示了这些概念。

AngularJS 指令(Directives)实践指南(2)

2014-03-12 10:22 陈鑫伟 编译 伯乐在线 我要评论(0) 字号:T | T
一键收藏,随时查看,分享好友!

一个指令用来引入新的HTML语法。指令是DOM元素上的标记,使元素拥有特定的行为。举例来说,静态的HTML不知道如何来创建和展现一个日期选择器控件。让HTML能识别这个语法,我们需要使用指令。指令通过某种方法来创建一个能够支持日期选择的元素。我们会循序渐进地介绍这是如何实现的。

AD:WOT2014课程推荐:实战MSA:用开源软件搭建微服务系统

compile函数

compile 函数在 link 函数被执行之前用来做一些DOM改造。它接收下面的参数:

  • tElement – 指令所在的元素
  • attrs – 元素上赋予的参数的标准化列表

要注意的是 compile 函数不能访问 scope,并且必须返回一个 link 函数。但是如果没有设置 compile 函数,你可以正常地配置 link 函数,(有了compile,就不能用link,link函数由compile返回)。compile函数可以写成如下的形式:

  1. app.directive('test'function() {  
  2.   return {  
  3.     compile: function(tElem,attrs) {  
  4.       //do optional DOM transformation here  
  5.       return function(scope,elem,attrs) {  
  6.         //linking function here  
  7.       };  
  8.     }  
  9.   };  
  10. });  

大多数的情况下,你只需要使用 link 函数。这是因为大部分的指令只需要考虑注册事件监听、监视模型、以及更新DOM等,这些都可以在 link 函数中完成。 但是对于像 ng-repeat 之类的指令,需要克隆和重复 DOM 元素多次,在 link 函数执行之前由 compile 函数来完成。这就带来了一个问题,为什么我们需要两个分开的函数来完成生成过程,为什么不能只使用一个?要回答好这个问题,我们需要理解指令在Angular中是如何被编译的!

指令是如何被编译的

当应用引导启动的时候,Angular开始使用 $compile 服务遍历DOM元素。这个服务基于注册过的指令在标记文本中搜索指令。一旦所有的指令都被识别后,Angular执行他们的 compile 方法。如前面所讲的,compile 方法返回一个 link 函数,被添加到稍后执行的 link 函数列表中。这被称为编译阶段。如果一个指令需要被克隆很多次(比如 ng-repeat),compile函数只在编译阶段被执行一次,复制这些模板,但是link 函数会针对每个被复制的实例被执行。所以分开处理,让我们在性能上有一定的提高。这也说明了为什么在 compile 函数中不能访问到scope对象。 在编译阶段之后,就开始了链接(linking)阶段。在这个阶段,所有收集的 link 函数将被一一执行。指令创造出来的模板会在正确的scope下被解析和处理,然后返回具有事件响应的真实的DOM节点。

改变指令的Scope

默认情况下,指令获取它父节点的controller的scope。但这并不适用于所有情况。如果将父controller的scope暴露给指令,那么他们可以随意地修改 scope 的属性。在某些情况下,你的指令希望能够添加一些仅限内部使用的属性和方法。如果我们在父的scope中添加,会污染父scope。 其实我们还有两种选择:

  • 一个子scope – 这个scope原型继承子父scope。
  • 一个隔离的scope – 一个孤立存在不继承自父scope的scope。

这样的scope可以通过指令定义对象中 scope 属性来配置。下面的代码片段是一个例子:

  1. app.directive('helloWorld'function() {  
  2.   return {  
  3.     scope: true,  // use a child scope that inherits from parent  
  4.     restrict: 'AE',  
  5.     replace: 'true',  
  6.     template: '<h3>Hello World!!</h3>' 
  7.   };  
  8. });  

上面的代码,让Angular给指令创建一个继承自父socpe的新的子scope。 另外一个选择,隔离的scope:

  1. app.directive('helloWorld'function() {  
  2.   return {  
  3.     scope: {},  // use a new isolated scope  
  4.     restrict: 'AE',  
  5.     replace: 'true',  
  6.     template: '<h3>Hello World!!</h3>' 
  7.   };  
  8. });  

这个指令使用了一个隔离的scope。隔离的scope在我们想要创建可重用的指令的时候是非常有好处的。通过使用隔离的scope,我们能够保证我们的指令是自包含的,可以被很容易的插入到HTML应用中。 它内部不能访问父的scope,所保证了父scope不被污染。 在我们的 helloWorld 指令例子中,如果我们将 scope 设置成 {},那么上面的代码将不会工作。 它会创建一个新的隔离的scope,那么相应的表达式 {{color}} 会指向到这个新的scope中,它的值将是 undefined. 使用隔离的scope并不意味着我们完全不能访问父scope的属性。其实有一些技术可以允许我们访问父scope的属性,甚至监视他们的变化。我们会在指令这个系列的第二部分中讨论这些技术,以及一些更高级的概念,比如 Controller 函数。 第二部分也会和你一起使用Angular指令创建一个较为丰富的记事本应用。 所以,请保持关注。

转载于:https://www.cnblogs.com/xihuafeiyu/articles/3747157.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/460358.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构四双向链表

双向链表也叫双链表&#xff0c;是链表的一种&#xff0c;它的每个数据结点中都有两个指针&#xff0c;分别指向直接后继和直接前驱。所以&#xff0c;从双向链表中的任意一个结点开始&#xff0c;都可以很方便地访问它的前驱结点和后继结点。而之前的单链表为单向链表&#xf…

smtplib python教程_Python使用poplib模块和smtplib模块收发电子邮件的教程

poplib模块接收邮件python的poplib模块是用来从pop3收取邮件的&#xff0c;也可以说它是处理邮件的第一步。POP3协议并不复杂&#xff0c;它也是采用的一问一答式的方式&#xff0c;你向服务器发送一个命令&#xff0c;服务器必然会回复一个信息。pop3命令码如下&#xff1a;命…

C#发送电子邮件 (异步) z

///验证电子邮件的正则表达式 string emailStr "^([\w-\.])((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]\.)))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"; /// <summary> /// 异步发送电子邮件 /// </summary> /// <p…

Linux服务器的初步配置流程

开发网站的时候&#xff0c;常常需要自己配置Linux服务器。 本文记录配置Linux服务器的初步流程&#xff0c;也就是系统安装完成后&#xff0c;下一步要做的事情。这主要是我自己的总结和备忘&#xff0c;如果有遗漏&#xff0c;欢迎大家补充。 下面的操作针对Debian/Ubuntu系统…

C语言趣味程序百例精解

1.绘制余弦曲线 在屏幕上用“*”显示0~360度的余弦函数cos(x)曲线 *问题分析与算法设计 如果在程序中使用数组&#xff0c;这个问题十分简单。但若规定不能使用数组&#xff0c;问题就变得不容易了。 关键在于余弦曲线在0~360度的区间内&#xff0c;一行中要显示两个点&#xf…

cocos2dx 圆盘抽奖_cocoscreator之微信小游戏的抽奖转盘

许多小游戏里面都有涉及到抽奖环节&#xff0c;所以就可能会用到抽奖转盘的制作&#xff0c;今天分享一个自己左转盘的小小过程。1、准备材料过程不多说&#xff0c;拼完界面之后大概是这样的&#xff1a;2、给界面绑定脚本&#xff0c;在脚本的properties里面绑定转盘节点&…

测试报告分析

测试分析报告 1&#xff0e;引言 1 1.1编写目的 1 1.2项目背景 1 1.3参考资料 2 2&#xff0e;测试计划执行情况 2 2.1测试项目 2 2.2测试机构和人员 3 2.3测试结果 3 3&#xff0e;软件需求测试结论 7 4&#xff0e;评价 7 4.1软件能力 7 4.2缺陷和限制 7 4.3建议 7 4.4测试结…

不要学习代码,要学会思考(转)

英文原文&#xff1a;Dont learn to code, learn to think 译/赖信涛 这是一个人人都在学习编程的时代&#xff1a;Code.org请了比尔盖茨&#xff0c;马克扎克伯格和克里斯波什等这些名人&#xff0c;来告诉你&#xff0c;每个人都可以编程&#xff1b;CoderDojo’s在各个国家悄…

python读取多个sheet文件_PythonPandas excel文件如何一次读取所有工作表,并再次写入多个工作表?,pythonpandasexcel,一次性,全部,sheet,重新...

关于如何一次性读取全部sheet&#xff0c;可看我之前写的一篇博客&#xff1b;本文重点讲述如何对同一个excel文件一次性写入多个sheet数据代码示例&#xff1a;import pandas as pdwriter pd.ExcelWriter("新数据.xlsx")sheet1Data [] # 这个为要向Sheet1写入的数…

stdin,stdout,stderr

我们在写C程序时经常遇到printf&#xff08;&#xff09;&#xff0c;fprintf&#xff08;&#xff09;&#xff0c;perror&#xff08;&#xff09;&#xff0c;这些东西到底有什么作用。说到这不得不提及stdin&#xff0c;stdout&#xff0c;stderr。想想&#xff0c;我们在用…

Hadoop的改进实验(中文分词词频统计及英文词频统计)(4/4)

声明&#xff1a; 1&#xff09;本文由我bitpeach原创撰写&#xff0c;转载时请注明出处&#xff0c;侵权必究。 2&#xff09;本小实验工作环境为Windows系统下的百度云&#xff08;联网&#xff09;&#xff0c;和Ubuntu系统的hadoop1-2-1&#xff08;自己提前配好&#xff0…

简单的日历小程序

一个可以查询1900年之后的所有年份当月月历。 import java.util.Scanner; public class Calendar {//输入年月输出当月日历public static void main(String[] args) {Scanner input new Scanner(System.in);System.out.println("请输入年份");int year input.nextI…

python龟图_python学习turtle(龟图标状态)

2019独角兽企业重金招聘Python工程师标准>>>记录学习turtle.hideturtle()turtle.ht()&#xff0c;隐藏龟图标。turtle.showturtle()turtle.st()&#xff0c;显示龟图标。turtle.isvisible()&#xff0c;龟是否显示。显示返回true&#xff0c;否则返回false。turtle.sh…

spring mvc相关问题

1&#xff1a; 基于注解的SpringMVC简单介绍 2&#xff1a; spring组件扫描<context:component-scan/>使用详解 3&#xff1a; springMvc 注解配置例子

C# - 创建List属性的简单方法

不用担心List没有创建问题。 private ObservableCollection<EquipmentItem> _optionalCollection;public ObservableCollection<EquipmentItem> OptionalCollection{get{if (this._optionalCollection null){this._optionalCollection new ObservableCollection&…

旋转函数_【视频课】:一次函数拓展应用(图象的平移、旋转、轴对称及5种解题方法)...

请点击上方“出彩数学”可以免费订阅哦停课不停学★ 特别关注&#xff1a;今日头条、西瓜视频——初三中考解题方法与技巧、初一、初二的同步讲解视频&#xff0c;正在陆续上传&#xff0c;请关注今天头条或西瓜视频(下载APP&#xff0c;搜索“出彩数学”&#xff0c;关注即可…

c语言中,关于延迟函数的理解

对于延迟&#xff0c;有些c基础的人都能够做到用for或while来实现 例如&#xff1a; #include <stdio.h>int main() {int i, j, k;for (i 1; i < 1000; i){for (j 1; j < 1000; j){for (k 1; k < 1000; k){}}}printf("hello\n");return 0; }1234…

static方法不能直接访问类内的非static变量和不能调用this,super语句分析

大家都知道在static方法中&#xff0c;不能访问类内非static成员变量和方法。可是原因是什么呢&#xff1f; 这首先要从static方法的特性说起。static方法&#xff0c;即类的静态成员经常被称为“成员变量”&#xff08;class members&#xff09;&#xff0c;对于静态成员变量…

C++ Qt 访问权限总结

总结&#xff1a;C的访问修饰符的作用是以类为单位&#xff0c;而不是以对象为单位。 通俗的讲&#xff0c;同类的对象间可以“互相访问”对方的数据成员&#xff0c;只不过访问途径不是直接访问. 步骤是&#xff1a;通过一个对象调用其public成员函数&#xff0c;此成员函数可…

火山去水印链接_在线批量去水印下载快手图集视频、抖音、火山等平台方法技巧!...

不管是做自媒体还是做电商或是工作素材采集&#xff0c;都离不开视频&#xff0c;视频比文字更好展示出产品、细节内容&#xff0c;就好比我们经常看的抖音、快手、火山、皮皮虾之类的短视频里面就有很多优秀的素材&#xff0c;相信有采集过的朋友都会遇到平台水印这个问题吧&a…