前面一直在说自定义指令,但是却一直没有一次系统地去了解,现在需要我们一起来学习如何去使用自定义指令,去丰富html标签、属性,实现多元化、多功能的标签(或是属性)。辣么,啥是指令?要了解指令,首先需要了解AngularJs的HTML编译器,简单地说让浏览器认识你自定义指令或是Angular的指令集,将其行为运用到DOM上(视图),分两个过程编译和链接,编译阶段是遍历DOM并且收集所有的相关指令,生成一个链接函数;链接阶段是给通过编译阶段调用所说的链接函数来将模板与作用域链接起来,绑定一个作用域,生成一个动态的视图。作用域模型的任何改变都会反映到视图上,并且视图上的任何用户操作也都会反映到作用域模型。

那么说到底,由某个属性、元素名称、css类名出现而导致的行为,或者说是DOM的变化,能让你以一种声明式的方法来扩展HTML表示能力,这就是指令!

官网(忽略,http://t.cn/RUbL4rP)也写了一个比较详细的指令demo(具体属性分析如下):

var myModule = angular.module(...);

myModule.directive('directiveName', function factory(injectables) { //工厂函数里面injectables是何意呢?望知道的人告知
var directiveDefinitionObject = {
priority: , //优先级priority,Dom里面会有很多指令,定义优先级,可以使此指令优先执行
     terminal:false, //如果被设置为true,那么该指令就会在同一个DOM的指令集和中最后被执行
template: '<div></div>', // or // function(tElement, tAttrs) { ... },
// templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... }, //template或templateUrl顾名思义就是模板文件,可以编写,也可以url,也可以是function(tElement,tAttrs){ return ... ;} replace: false, //是否替换现在的元素 transclude: false, //重要属性之一,配合ng-transclude使用,为true时,可以将原元素的内容(html、其他指令)提取到带有指令ngTransclude的元素内,下面有例子说明!(注:指令的内部可以访问外部指令的作用域,并且模板也可以访问外部的作用域对象) restrict: 'A', //以哪种形式声明指令行为的格式,有AECM,分别是属性<div my-directive="exp"> </div> 、元素*<my-directive></my-directive> 、 class*<div class="my-directive: exp;"></div> 、注释<!-- directive: my-directive exp --> templateNamespace: 'html', //模板的命名空间,有'html'、'svg'等,默认为'html' scope: false, //是否创造一个新的作用域(针对指令)
     /*scope是最难理解的一个属性*/ controller: function($scope, $element, $attrs, $transclude, otherInjectables) {...
}, //控制器的构造对象,预编译阶段执行,$scope当前作用域,$element当前元素,$attrs当前元素的属性集合,并且它是共享的,其他指令可以通过它的名字得到(参考依赖属性(通过require属性引入)。这就使得指令间可以互相交流来扩大自己的能力。当然也可以是控制        器名字(那么此控制器需要在应用声明好,这样便可以通过注入$attrs、$element操纵指令对应模板的dom),$transclude,用来操作嵌入作用域对应的dom,也就是被提取到ngTransclude的元素里面的dom了,下面有例子说明! controllerAs: 'stringAlias', //定义控制器的别名 require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'], // 请求将另一个控制器作为参数传入到当前链接函数。 这个请求需要传递被请求指令的控制器的名字。之前有例子关于表单自定义                        验证有使用到,学习笔记-AngularJs(八) compile: function compile(tElement, tAttrs, transclude) { //tElement指令所在的元素,tAttrs指令所在元素属性集合
return {
pre: function preLink(scope, iElement, iAttrs, controller) {...
},
post: function postLink(scope, iElement, iAttrs, controller) {...
}
}
// or
// return function postLink( ... ) { ... } //编译函数是用来处理需要修改模板DOM(执行于放到dom之前的dom操作)的情况的。因为大部分指令都不需要修改模板,所以这个函数也不常用。返回的是函数或是对象,返回函数时等效于link链接函数
},
// or
// link: { //链接函数负责注册DOM事件和更新DOM。它是在模板被克隆之后执行的。 它也是大部分指令逻辑代码编写的地方。scope当前作用域,iElement当前元素,iAttrs当前元素的属性集合,controller就是上面require属性的值,于是就可以调用require进来的控制            器的属性方法,(包括之前讲的ngModel或是其他指令controller和controllerAs定义的有控制器名的控制器方法)
// pre: function preLink(scope, iElement, iAttrs, controller) { ... }, // post: function postLink(scope, iElement, iAttrs, controller) { ... } // } // or // link: function postLink( ... ) { ... }
};
return directiveDefinitionObject;
});

compile和link选项是互斥的。如果同时设置了这两个选项,那么会把compile所返回的函数当作链接函数,而link选项本身则会被忽略。

编译函数负责对模板DOM进行转换。链接函数负责将作用域和DOM进行链接。

上面demo有些属性在实际操作上,都是取默认的属性,那么官网将其简化成了这个样子:

var myModule = angular.module(...);

myModule.directive('directiveName', function factory(injectables) { //此处需要注意,在视图引入指令时,采用的是骆峰命名法,所以调用时应该是directive-name
var directiveDefinitionObject = {
link: function postLink(scope, iElement, iAttrs) { ... }
};
return directiveDefinitionObject;
// or
// return function postLink(scope, iElement, iAttrs) { ... }
});

到这里还是需要编写些demo,才能起到学习的效果!

在之前的学习笔记-AngularJs(八)里面就有一个自定义表单验证的demo,情景是这样的,在input框里面不能写入“xiaobin”,主要是对ngModel中$setValidity(validationErrorKey, isValid);$setViewValue(value, trigger);在双向绑定中是如何实现scope->view、view->scope之间的那个验证和格式化的学习,没看过的话,可以去看一下,虽然理解得不透彻!下面贴一下主要代码:

var custom = angular.module('customControl', ['ngSanitize']);

custom.directive("noxiaobin", function () {
return {
restrict: "A",
require: "?ngModel",
link: function (scope, element, attrs, ngModel) {
if (!ngModel) return;
ngModel.$parsers.push(function (v) { //传说中的验证器 if (v != "xiaobin") {
ngModel.$setValidity('noxiaobin', true); //通过获取从dom过来的值,然后进行验证,使用$setValidity('noxiaobin', true);改变noxiaobin的值,然后反馈会dom
return v;
} else {
ngModel.$setValidity('noxiaobin', false);
return undefined;
} });
}
}
});

在这里,我们另外写一个比较综合的例子,dialog.html可到github下载(github地址:https://github.com/xiaobin5201314/AngularJS-Learning/tree/master/block-example/指令-13

<!doctype html>
<html ng-app='directiveModule'>
<head>
<meta charset="utf8"/>
<script src="../jquery.js"></script>
<script src="../angular.js"></script>
<script src="../bootstrap.min.js"></script>
<link rel="stylesheet" href="../bootstrap.min.css"> <script>
var directive = angular.module('directiveModule', []); //这里是验证指令的内部可以访问外部指令的作用域,这样我们在dialog.html也可以查看到遍历出来的的arrs
directive.controller("directiveControl",["$scope",function($scope){
$scope.arrs=["我是内容一","我是内容二","我是内容三"];
$scope.hide=false;
}]) //将任意可以被注入的ng服务注入到控制器中,便可以在指令中使用它了。控制器中也有一些特殊的服务可以被注入到指令当中,当然这是在应用上声明、也可以直接写在controller属性上
directive.controller("directiveChildControl",['$scope','$attrs','$element','$transclude',function($scope,$attrs,$element,$transclude){
$element.css('border', '#fff'); //改变模板dom里面的结构
$transclude(function (clone) { //这是操作嵌入的作用域里面的dom
var a = angular.element('<a>');
a.attr('href', 'http://www.cnblogs.com/wuxiaobin');
a.text('我的博客原地址');
$element.find('.modal-body').append(a);
});
}]) directive.directive("dialog", function () {
return {
restrict: "AE",
replace: true,
transclude:true, //配合ng-transclude使用,为true时,可以将原元素的内容(html、其他指令)提取到带有指令ngTransclude的元素内
controller:'directiveChildControl',
scope:{
title:"@" //模板也可以访问外部的作用域对象,dialog.html的{{title}}正是局部作用域访问父作用域的所产生的效果,这样可以很好实现我们的组件的设计思想,但对于@、=、&的写法有些不理解,望有更好的学习资料可以提供一下,当然搞懂了,也会更新上来
},
templateUrl: 'dialog.html',
link: function(scope, element, attrs, ctrl) {
console.log(element.html());
element.find('.modal-title').css('color', 'red');
}
}
}); </script> </head>
<body ng-controller="directiveControl"> <button class="btn btn-lg btn-primary " data-toggle="modal" data-target="#myModal">弹出模态框</button>
<dialog title="我是传递过来的title">
<span ng-repeat="arr in arrs" ng-hide="hide">
{{$index}}-{{arr}} <br>
</span>
我的内容即将保存,被提取到<code> span[ng-transclude] </code>上
</dialog> </body>
</html>

效果图:

学习笔记-AngularJs(十)的更多相关文章

  1. VSTO学习笔记(十四)Excel数据透视表与PowerPivot

    原文:VSTO学习笔记(十四)Excel数据透视表与PowerPivot 近期公司内部在做一种通用查询报表,方便人力资源分析.统计数据.由于之前公司系统中有一个类似的查询使用Excel数据透视表完成的 ...

  2. VSTO 学习笔记(十二)自定义公式与Ribbon

    原文:VSTO 学习笔记(十二)自定义公式与Ribbon 这几天工作中在开发一个Excel插件,包含自定义公式,根据条件从数据库中查询结果.这次我们来做一个简单的测试,达到类似的目的. 即在Excel ...

  3. VSTO学习笔记(十五)Office 2013 初体验

    原文:VSTO学习笔记(十五)Office 2013 初体验 Office 2013 近期发布了首个面向消费者的预览版本,我也于第一时间进行了更新试用.从此开始VSTO系列全面转向Office 201 ...

  4. VSTO 学习笔记(十)Office 2010 Ribbon开发

    原文:VSTO 学习笔记(十)Office 2010 Ribbon开发 微软的Office系列办公套件从Office 2007开始首次引入了Ribbon导航菜单模式,其将一系列相关的功能集成在一个个R ...

  5. Python学习笔记(十四)

    Python学习笔记(十四): Json and Pickle模块 shelve模块 1. Json and Pickle模块 之前我们学习过用eval内置方法可以将一个字符串转成python对象,不 ...

  6. Python学习笔记(十)

    Python学习笔记(十): 装饰器的应用 列表生成式 生成器 迭代器 模块:time,random 1. 装饰器的应用-登陆练习 login_status = False # 定义登陆状态 def ...

  7. Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例

    目录 前言 搭建项目及其它准备工作 创建数据库 创建Koa2项目 安装项目其它需要包 清除冗余文件并重新规划项目目录 配置文件 规划示例路由,并新建相关文件 实现数据访问和业务逻辑相关方法 编写mys ...

  8. Nodejs学习笔记(十六)--- Pomelo介绍&入门

    目录 前言&介绍 安装Pomelo 创建项目并启动 创建项目 项目结构说明 启动 测试连接 聊天服务器 新建gate和chat服务器 配置master.json 配置servers.json ...

  9. [转]Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例

    本文转自:https://www.cnblogs.com/zhongweiv/p/nodejs_koa2_webapp.html 目录 前言 搭建项目及其它准备工作 创建数据库 创建Koa2项目 安装 ...

随机推荐

  1. Python:判断文本中的用户名在数据库中是否存在,存在返回1,不存在返回0

    下面是我写的python的一个小脚本,作用是:判断文本中的用户名在数据库中是否存在,存在返回1,不存在返回0.用的是MySQL数据库. 要注意的是:strip函数的使用,该函数的作用是去除字符串两端多 ...

  2. Oracle 11g R2创建数据库之DBCA静默方式

    通常创建Oracle数据库都是通过DBCA(Database Configuration Assistant)工具完成的,DBCA工具可以通过两种方式完成建库任务,即图形界面方式和静默命令行方式.既然 ...

  3. vue-amap | 基于 Vue 2.x 与高德的地图组件

    vue-amap | 基于 Vue 2.x 与高德的地图组件 参考:https://elemefe.github.io/vue-amap/#/

  4. 谈谈 ArrayList 和 LinkedList 的区别

    ArrayList: 基于动态数组的数据结构:删除和插入操作每次都要改变数组的长短,比较消耗性能,但是查询会比较快 除非插入和删除的位置都在表末尾,否则代码开销会很大,因为里面需要数组的移动. Lin ...

  5. 使用Python在自己博客上进行自动翻页

    先上一张代码及代码运行后的输出结果的图! 下面上代码: # coding=utf-8 import os import time from selenium import webdriver #打开火 ...

  6. Centos7 升级 Ruby

    Centos7通过yum 安装的Ruby 是2.0版本.版本较低,需要升级到2.5以上版本. #yum 安装ruby yum install ruby #查看ruby版本 ruby -v 以下开始升级 ...

  7. Docker Swarm volume 数据持久化

    Docker Swarm volume 数据持久化 volume 是将宿主级的目录映射到容器中,以实现数据持久化. 可以用两种方式来实现: volume 默认模式:工作节点宿主机数据同步到容器内. v ...

  8. java excel大数据量导入导出与优化

    package com.hundsun.ta.utils; import java.io.File; import java.io.FileOutputStream; import java.io.I ...

  9. MVC输出缓存(OutputCache参数详解)

    版权声明:本文为博主原创文章,未经博主允许转载随意. https://blog.csdn.net/kebi007/article/details/59199115 1.学习之前你应该知道这些 几乎每个 ...

  10. Android中的task和stack

    今天在重新理了一遍intent的过程中发现task是一个神奇的东西,而它又和stack有着很深的联系.task顾名思义是一个任务,但是这个任务可不一定只是来自一个app,比如我用微信来发一张图片,那么 ...