之前写过一篇了 http://www.cnblogs.com/keatkeat/p/3903673.html

但某些部分写的不太清楚,甚至有点错误,所以今天特地在这里再来谈谈。

这篇主要是说指令的隔离还有和controller的沟通.

指令的运行过程基本上我们可以简单的理解为 : template -> compile -> controller -> pre-link -> post-link

我们通常只是用到post link,但如果你的指令有嵌套,子层需要父层的一些值的话,可以考虑把这些初始值写在 controller 或者是 pre-link

pre-link 是上层到下层调用, post-link 则相反下至上调用.

在开发中当一个内容经常重复时,我们就会把它封装成指令。

这种组件的思想可以节省很多开发时间。

而封装的指令不太可能每一次使用都是一模一样的。

所以我们必须可以调整它。

一般上我们使用 attr.  (就好象函数和参数的感念)

<div ng-controller="ctrl">
<dir data-obj="obj" data-string="{{string}}" data-method="method(outsideParam,insideParam)" ></dir>
</div> <script>
var app = angular.module("app", []);
app.directive("dir", ["$parse",function ($parse) {
return {
restrict: "E",
template: '<div>' +
'{{ obj.value }}' +
'{{ string }}' +
'<div ng-click="click()"></div>' +
'</div>',
link: function (scope, elem, attr) {
//scope.$parent 是controller scope, 隔离只是表示没有继承,但是parent还是可以访问得到。
scope.click = function () {
scope.method({ insideParam: "88" }); //这里你可以选择要不要覆盖掉外面的 outsideParam. 非常灵活
}
},
scope: {
obj: "=", //双向绑定,内部变化会在digest的时候同步去外面
//obj: "=object", //data-object="obj" 如果你的属性名字很不一样的话,angular 只会把 a-b-c 换成 驼峰式
//obj : "=?object", //加 ? 表示这个属性不一定会有。如果没写 ? 你使用 "=" 但是写属性的话是会报错的哦
string: "@", //单向绑定 (只限于string,int, object array can't), 内部改变不会影响外面
method : "&" //绑定方法, 注意param, 它是可以像 bind 那样,放入不同阶层的 params
}
}
}])
app.controller("ctrl", ["$scope", "$timeout", function ($scope, $timeout) {
$scope.obj = {
value: "lu xiao feng"
}
$scope.string = "luxiaofeng";
$scope.outsideParam = "77";
$scope.method = function (outsideParam, insideParam) {
log(outsideParam); //77 这个是预先设定的
log(insideParam); //
}
}]);
</script>

更新 : 2015-07-01

transclude

参考 : https://docs.angularjs.org/api/ng/service/$compile  (里面的 transclusion)

在做指令的时候,我们需要很多动态的东西,像之前的属性,我们可以通过 scope : { "=","@","&" } 来实现动态。

那么如果我们想实现模板或者说某部分的element动态的话,我们可以使用 translude

<div ng-controller="ctrl">
<dir>
<span>{{ name }}</span>
</dir>
</div>
<script>
var app = angular.module("app", []);
app.controller("ctrl", ["$scope", "$timeout", function ($scope, $timeout) {
$scope.name = "keatkeat";
}]);
app.directive("dir", [function () {
return {
restrict: "E",
transclude: true,
template: '<div>' +
'<div ng-transclude></div>' +
'</div>',
link: function (scope, elem, attr, ctrl, $transclude) { },
scope: {}
}
}]);
</script>

只要在指令注册时写上 translude : true 就可以了。

ng 会把指令中间的 element keep 起来, 然后放到 ng-transclude 里头 .

ng-transclude 是 angular 写好的一个指令很方便使用。

如果你想发挥到淋漓精致的话,有几点你需要搞清楚!

compile : function (elem,attr,$transclude) | link : function (scope,elem,attr,ctrl,$transclude)

controller : ["$transclude",function($transclude){}]

compile,link,controller 都可以获取到 $transclude 方法。

这个方法其实就是 linkFn , ng 预先把指令内的elem 拿去$compile 了

$transclude(scope,cloneAttachFn)

一般上这个 $tranclude 是这样用的

$transclude(function (clone, scope) {
log("trs : " + scope.$id); <- 自己是一个新的scope
log(scope.$parent); <- 指令的scope ,但却继承了 ctrl 的 scope 哦 ! elem.empty(); elem.append(clone); 最后就append 这个clone 出去就行了
});

很重要 : 如果没有指定 scope 的话,scope 是一个新的scope, 它继承了ctrl , 但它是指令的孩子。 这有点难理解,但是好处很多 ^^ 下面是原文的解释

When you call a transclude function it returns a DOM fragment that is pre-bound to a transclusion scope. This scope is special, in that it is a child of the directive's scope (and so gets destroyed when the directive's scope gets destroyed) but it inherits the properties of the scope from which it was taken.

当父指令有 transclude 时,子指令也可以调用的到, 这也是 ng-transclude 能实现的原因了。

更新 : 2016-03-01

angular 1.5.0 版本 translude 有了多一个 mutilple 的功能

参考 : http://blog.thoughtram.io/angular/2015/11/16/multiple-transclusion-and-named-slots.html

<product>
@*<detail-one>
<div>detail one</div>
</detail-one>*@
<detail-two>
<div>detail two</div>
</detail-two>
</product>
app.directive("product", [function () {
return {
restrict: "E",
transclude: {
//note :
//这对象是一个对接对象, key 对应内部调用 , value 对应外部 (这个算是angular规范,不只是transclude有这样的设计)
detailOne: "?detailOne", // ? 代表可有可无
detailTwo: "detailTwo"
},
template: [
'<div>',
'<div>',
//如果外部没有传进来,会使用default的做显示,有传进来的话则会覆盖掉default
'<div ng-transclude="detailOne" >default value for details one</div>',
'</div>',
'<br/>',
'<div>',
'<div ng-transclude="detailTwo" >default value for details one</div>',
'</div>',
'</div>',
].join(''),
link: function (scope, elem, attr) {}
}
}]);

更新 : 2016-03-01

1.5.0 版本 angular 多了一个 component 组件

refer :

https://docs.angularjs.org/guide/component

https://toddmotto.com/exploring-the-angular-1-5-component-method/

文章开头就说明了 a Component is a special kind of directive, 组件是一种特别的指令 (意思是指令基本上可以完成所有组件的功能)

那组件主要的好处就是它比较简单理解和使用, 迈向 angular 2.0 你应该尽可能的使用组件 (当然如果组件不满足需求,指令依然是需要的)

这里我主要是讲概念的东西。

组件主要就是简化了以前指令的复杂性。所以你会发现他移除了很多我们不常用到的东西。

比如 : compile, link, scope, multiElement, priority, restrict 都移除了。

而且scope直接就是 isolate 的

所以当我们在使用组件时,我们也必须延着这种简单的思路去设计。不要再去使用$scope继承等等。

组件和外部沟通使用的是 bindings , 这个等价于 bindToController + scope : { @,&,= }

1.5.0 多了一个 "<" 符号,叫单向绑定

我们知道以前我们要传 string,int 我们用 "@"

我们要传对象,要双向,我们用 "="

但是我们要传对象,但是不要双向,我们就没有的用了,而现在可以使用 "<"

这里给大家复习一下 :

@ 外面可以改变里面,里面不可以改变外面 (only for 值类型 e.g. string,int)
= 里面外面完全同步 (如果是obj,array的话,在某些情况下是会打断引用的,但即使打断他还是能同步key,value)
< 和 = 一样,区别在里面不会同步去外面了。(当然如果obj引用一样的话,你只改prop还是会影响到外面啦)

组件的require和指令也有点不一样 (多了一个叫 $onInit 的东东)

app.component("product", {
template: [
'<div>',
'<color></color>',
'</div>'
].join(''),
controller: ["$scope", "$timeout", function ($scope, $timeout) {
this.shareMethod = function () {
console.log("share method");
}
}]
});
app.component("color", {
template: [
'<div>color</div>'
].join(''),
require : {
productCtrl : "^product"
},
controller: ["$scope", function ($scope) {
this.$onInit = function () {
this.productCtrl.shareMethod();
}
}]
});

require 向上寻找 component 然后在 $onInit 的时候才会注入到ctrl内,require 对象也是一个mapping对象.

angularjs directive and component 指令与组件 ( 1.5.0 以后 )的更多相关文章

  1. AngularJS:directive自定义的指令

    除了 AngularJS 内置的指令外,我们还可以创建自定义指令. 你可以使用 .directive 函数来添加自定义的指令. 要调用自定义指令,HTML 元素上需要添加自定义指令名. 使用驼峰法来命 ...

  2. 学习AngularJs:Directive指令用法(完整版)

    这篇文章主要学习AngularJs:Directive指令用法,内容很全面,感兴趣的小伙伴们可以参考一下   本教程使用AngularJs版本:1.5.3 AngularJs GitHub: http ...

  3. 学习AngularJs:Directive指令用法

    跟我学AngularJs:Directive指令用法解读(上) http://blog.csdn.net/evankaka/article/details/51232895 跟我学AngularJs: ...

  4. angularjs directive学习心得

    一些常见的错误 在angularjs里,创建directive时,directive的名称应该要使用驼峰式,例如myDirective,而在html里要调用它的时候,就不能用驼峰式了,可以用my-di ...

  5. 带你走近AngularJS - 创建自己定义指令

    带你走近AngularJS系列: 带你走近AngularJS - 基本功能介绍 带你走近AngularJS - 体验指令实例 带你走近AngularJS - 创建自己定义指令 ------------ ...

  6. 带你走近AngularJS 之创建自定义指令

    带你走近AngularJS 之创建自定义指令 为什么使用AngularJS 指令? 使用过 AngularJS 的朋友应该最感兴趣的是它的指令.现今市场上的前端框架也只有AngularJS 拥有自定义 ...

  7. Angularjs directive全面解读(1.4.5)

    说到Angularjs directive即指令,可以这么说Angularjs的灵魂就是指令,学会Angularjs指令那么你的Angularjs的武功就修炼了一半了,当然这只是鄙人的一点点独到见解, ...

  8. angular5 directive和component的区别

    指令分为三类,组件,属性指令和结构性指令 组件(Component directive):UI组件,继承于Directive: 属性指令(Attribute directive):改变组件的样式: 结 ...

  9. 基于AngularJS的个推前端云组件探秘

    基于AngularJS的个推前端云组件探秘 AngularJS是google设计和开发的一套前端开发框架,帮助开发人员简化前端开发的负担.AngularJS将帮助标准化的开发web应用结构并且提供了针 ...

随机推荐

  1. 20个Linux服务器性能调优技巧

    Linux是一种开源操作系统,它支持各种硬件平台,Linux服务器全球知名,它和Windows之间最主要的差异在于,Linux服务器默认情况下一般不提供GUI(图形用户界面),而是命令行界面,它的主要 ...

  2. DAY TRADER

    日内交易是一种交易模式,英文名字是daytrade,主要是指持仓时间短,不留过夜持仓的交易方式.日内交易捕捉入市后能够马上脱离入市成本的交易机会,入市之后如果不能马上获利,就准备迅速离场.因为这种交易 ...

  3. SQL - 添加外键

    不解释: ---先创建外键的column ALTER TABLE tblLicenses ADD ProductID int not null; ---添加外键 ALTER TABLE tblLice ...

  4. MyEclipse使用问题及解决方法

    1.MyEclipse报错:Eclipse javax.servlet.jsp.PageContext cannot be resolved to a type 原因是:jdk 里不包括servlet ...

  5. 使用cocoapods导入第三方后 报错_OBJC_CLASS_$_XXX

    我们手动导入第三方库的时候,感觉管理不是很方便,于是会选择使用Cocoapods管理.现在记录一下使用心得,当使用cocoapods导入afnetworking或者其他框架的时候,发现调用的时候总是报 ...

  6. MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)

    MySQL主从复制(Master-Slave)即同步与读写分离(MySQL-Proxy)即集群

  7. cocos2d 高仿doodle jump 无源代码

    1. 游戏视频 主角眼熟吗?没错,上次跑酷游戏中的"30"来Jump了,有三种道具.主角光环,竹蜻蜓.翅膀: 有两种怪物,螃蟹和鸟: 有5种板子.点击屏幕,30会把它的嘴巴3给发射 ...

  8. [转] 使用Spring Boot和Gradle创建项目

    Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的 ...

  9. git 更换远程仓库地址

    1. 更改软件仓库指向.在github改了用户名和仓库名称后,仓库地址也相应的发生的变化,这时候就需要更新本地仓库以指向新的远程仓库地址: $git remote set-url origin git ...

  10. C#之Linq学习笔记【转】

    写在前面 其实在09年就已经学习过Linq了,并被她那优美的语法所吸引,只是现在所在的公司还在使用VS2005在.Net2.0的框架下面的开发,所以Linq也很久没有用过了,最近看部门的同事对这个有些 ...