首先放官方文档地址:https://docs.angularjs.org/guide/directive

就我对directive的粗浅理解,它一般用于独立Dom元素的封装,应用场合为控件重用和逻辑模块分离。后者我暂时没接触,但数据交互部分却是一样的。所以举几个前者的例子,以备以后忘记。

directive本身的作用域$scope可以选择是否封闭,不封闭则和其controller共用一个作用域$scope。例子如下:

 <body ng-app="myApp" ng-controller="myCtrl">
<test-directive></test-directive>
<script>
angular.module("myApp",[])
.controller("myCtrl",function($scope){
$scope.data = {
name:"白衣如花"
};
})
.directive("testDirective",function(){
return {
restrict:"E",
template:"<h1>{{data.name||'未定义'}}</h1>"
}
});
</script>
</body>

显示结果为:白衣如花,可以知道directive中的data.name就是myCtrl控制器中的$scope.data.name。

那么封闭的directive呢?怎么封闭,封闭效果是什么样的,封闭后怎么数据交互?这些都是我这几天摸索的东西。

 <body ng-app="myApp" ng-controller="myCtrl">
<test-directive></test-directive>
<script>
angular.module("myApp",[])
.controller("myCtrl",function($scope){
$scope.data = {
name:"白衣如花"
};
})
.directive("testDirective",function(){
return {
restrict:"E",
scope: {},
template:"<h1>{{data.name||'未定义'}}</h1>"
}
});
</script>
</body>

结果显示为:未定义。所以在directive定义时,添加属性scope就可以把directive的作用域和父控制器的作用域分离开来。

好,了解了开放和封闭之后,进入主题,如何进行数据交互。个人觉得数据交互分为:父控制器获取directive的变量;directive获取父控制器的变量;父控制器调用directive的函数;directive调用父控制器的函数。

1.父控制器获取directive的变量。比如封装了一个输入框接受用户输入,父控制器点击搜索按钮要获取用户输入:

 <body ng-app="myApp" ng-controller="myCtrl">
<p>名字:{{outerName}}</p>
<test-directive inner-name="outerName"></test-directive>
<script>
angular.module("myApp",[])
.controller("myCtrl",function($scope){
})
.directive("testDirective",function(){
return {
restrict:"E",
scope: {
innerName: "="
},
template:"<input type='text' ng-model='innerName' placeholder='白衣如花'>"
}
});
</script>
</body>

显示结果如下:

分析:从数据流向说起,testDirective中的一个input输入绑定在innerName中,innerName是directive私有作用域拥有的变量,外部控制器不能直接用。通过innerName: "="传递给html中的inner-name属性,

而inner-name属性则绑定在外部控制器的outerName变量中,所以最后显示在最上面的<p>标签内。上述代码等价于如下代码:

<test-directive name="outerName"></test-directive>
scope: {
innerName: "=name"
},

由inerName: "="变成了innerName: "=name",而html属性绑定也由inner-name变成了name。

2.directive获取父控制器的变量。这个应用场合应该挺多的,比如公共的页眉页脚,公共的展示面板等。

这个用上面例子的"="一样可以实现,于是我们知道了"="是双向绑定。但是我们要防止directive内部意外修改数据该怎么办呢?于是单向绑定"@"就出场了。

 <body ng-app="myApp" ng-controller="myCtrl">
<input type='text' ng-model='outerName' placeholder='白衣如花'>
<test-directive inner-name="{{outerName}}"></test-directive>
<script>
angular.module("myApp",[])
.controller("myCtrl",function($scope){
})
.directive("testDirective",function(){
return {
restrict:"E",
scope: {
innerName: "@"
},
template:"<p>名字:{{innerName}}</p>" +
"<button ng-click='innerName=innerName+1'>点击</button>"
}
});
</script>
</body>

值得注意的是:@在html的属性绑定时需要{{}}开标识,而=则不用。我的理解是,对于父控制器而言,@是数据传递,而=是数据绑定,所以有这些区别。directive中加入了一个按钮用于验证修改数据后

父控制器是否发生改变,结果是=有变化,@无变化,很容易得出结论:=是双向绑定,@是单向绑定。

3.directive调用父控制器的函数。应用场合,暂时想不到(汗)。

变量用=和@来传递,函数则用&。例子如下:

 <body ng-app="myApp" ng-controller="myCtrl">
<p>名字:{{outerName}}</p>
<test-directive on-click="click(name)"></test-directive>
<script>
angular.module("myApp",[])
.controller("myCtrl",function($scope){
$scope.click = function (name) {
$scope.outerName = name || "白衣如花";
}
})
.directive("testDirective",function(){
return {
restrict:"E",
scope: {
onClick: "&"
},
template:"<input type='text' ng-model='innerName' placeholder='白衣如花'>" +
"<button ng-click='onClick({name: innerName})'>点击</button>"
}
});
</script>
</body>

数据传递流程和之上的例子差不多,唯一要注意的是参数传递时,{name: innerName}前者是形参,后者是实参。多个参数时,参数顺序不重要,形参一一对应。

4.父控制器调用directive的函数。这个是前段时间遇到的难点,情况较其他复杂一些。应用场合也很普遍,比如初始化,重置等。

 <body ng-app="myApp" ng-controller="myCtrl">
<button ng-click="click()">重置</button>
<test-directive action="action"></test-directive>
<script>
angular.module("myApp",[])
.controller("myCtrl",function($scope){
$scope.action = {};
$scope.click = function () {
$scope.action.reset();
}
})
.directive("testDirective",function(){
return {
restrict:"E",
scope: {
action: "="
},
template:"<input type='text' ng-model='name' placeholder='白衣如花'>",
controller: function ($scope) {
$scope.action.reset = function () {
$scope.name = "白衣如花"
}
}
}
});
</script>
</body>

又一次用到了=,利用了js中函数也是属性的原理。似乎,理解了=的双向绑定,就很容易调用directive内部函数了。但是初始化呢?

首先想到的是类似的=来引用传递:

 <body ng-app="myApp" ng-controller="myCtrl">
<test-directive action="action"></test-directive>
<script>
angular.module("myApp",[])
.controller("myCtrl",function($scope){
$scope.action = {};
$scope.action.init();
})
.directive("testDirective",function(){
return {
restrict:"E",
scope: {
action: "="
},
template:"<input type='text' ng-model='name' placeholder='白衣如花'>",
controller: function ($scope) {
$scope.action.init = function () {
$scope.name = "白衣如花"
}
}
}
});
</script>
</body>

但是运行却发现,错误显示$scope.action.init is not a function,看提示应该是运行到第7行的时候,$scope.action.init函数还未定义。怎么办呢?把directive提到controller之前试试?一样是错误。

嗯,可以不用函数,直接在directive的controller中执行$scope.name = "白衣如花",似乎很完美,但如果是有参数的初始化呢?事实上js分离后,我遇到的问题是根据http请求的返回结果来初始化directive,由于

网络快慢不一定,导致控件初始化时不一定有http请求的返回(没有有效的初始化参数),也不能保证http请求返回后directive已经初始化(不能用=来进行函数调用)。

需求很明了了,如果能监控参数变化,再执行初始化,此时能保证directive已经加载,而且有有效的参数。正好angularjs提供了$watch。代码如下:

 <body ng-app="myApp" ng-controller="myCtrl">
<test-directive action="action"></test-directive>
<script>
angular.module("myApp",[])
.controller("myCtrl",function($scope){
$scope.action = {name: "白衣如花"};
})
.directive("testDirective",function(){
return {
restrict:"E",
scope: {
action: "="
},
template:"<input type='text' ng-model='name' placeholder='白衣如花'>",
link: function (scope, elem, attrs) {
scope.$watch(attrs.action, function (value) {
scope.action.init();
})
},
controller: function ($scope) {
$scope.action.init = function () {
$scope.name = $scope.action.name
}
}
}
});
</script>
</body>

这是我对于directive数据交互的粗浅理解。想要更详细了解,请参看官方文档:https://docs.angularjs.org/guide/directive

angularJs中自定义directive的数据交互的更多相关文章

  1. AngularJS中自定义有关一个表格的Directive

    本篇体验在AngularJS中自定义一个有关表格的Directive.表格的需求包括: ● 表格结构 <table>    <thead>        <tr>  ...

  2. angularjs中的directive scope配置

    angularjs中的directive scope配置 定义directive其中重要的一环就是定义scope,scope有三种形式: 默认的scope,DOM元素上原有的scope scope: ...

  3. AngularJS中有关Directive的汇总

    本篇通过几个例子对AngularJS中的Directive进行汇总. 例子1,单向绑定和双向绑定 <html ng-app="myApp"> <head> ...

  4. AngularJS中使用Directive、Controller、Service

    AngularJS是一款非常强大的前端MVC框架.同时,它也引入了相当多的概念,这些概念我们可能不是太熟悉. (1)Directive 指令 (2)Controller 控制器 (3)Service ...

  5. Vue中独立组件之间数据交互

    独立组件之间数据交互:通过自定义事件 组件A中的[数据],传递给组件B 1.创建组件A,组件B 2.组件B在实例创建完成时就开始监听事件[等待接收数据]:钩子 3.组件A中触发事件,发送数据 注意:接 ...

  6. 关于angularjs 中自定义过滤器

    包子认为,在angularjs中,经常需要用到自定义过滤器,来过滤相应的功能,自定义过滤器非常的简单,我就直接贴代码啦 其中input就是你需要进行操作的对象,,,用法就直接就是 是不是很easy.. ...

  7. angularjs中的directive

    正在初学angularjs中,在网上看到一篇详细讲解directive指令的文章,于是就记录在这里和大家一起分享 angular.module('docsTransclusionExample', [ ...

  8. AngularJS中自定义过滤器

    AngularJS中为我们提供了一些内置的过滤器,这里列举一些自定义过滤器的场景. 自定义过滤器,不带参赛 //过滤 不带参赛 app.filter('ordinal', function () { ...

  9. angularJS中自定义指令

    学习了angularJS一周,但是大部分时间被自定义指令占用了.博主表示自学互联网好心塞的,发现问题的视觉很狭窄,这比解决问题要更难.这篇文章首先介绍了自定义,然后介绍了在使用自定义指令遇到的问题. ...

随机推荐

  1. Python 2.7.3 Time与DateTime格式化

    import time import datetime class TimeX: '''时间工具,目前用于格式化时间''' @staticmethod def GetLocalTimeString_T ...

  2. 解决Ubuntu Adobe Reader 菜单栏空白

    sudo gedit /usr/local/share/applications/AdobeReader.desktop将  ”Exec=acroread“ 用 ”Exec=env UBUNTU_ME ...

  3. [译]Java 设计模式之外观

    (文章翻译自Java Design Pattern: Facade) 外观设计模式隐藏了任务的复杂性而只是提供了一个简单的接口.一个非常好的例子就是计算机的启动.当一个计算机启动的时候,它涉及CUP. ...

  4. 通过如何通过js实现复制粘贴功能

    在ie中window.clipboardData(剪切板对象)是可以被获取,所以利用这个方法我们可以实现在IE当中复制粘贴的功能,demo如下! <html> <head> & ...

  5. 数据结构栈的java实现

    近来复习数据结构,自己动手实现了栈.栈是一种限制插入和删除只能在一个位置上的表.最基本的操作是进栈和出栈,因此,又被叫作“先进后出”表. 实现方式是这样的:首先定义了一个接口,然后通过这个接口实现了线 ...

  6. char* 转换成 CString

    真是有意思: CString mess ;    mess = m_chLocalIP; 这样OK,但是写在一行就会报错 CString mess  = m_chLocalIP; //有问题

  7. noip推荐系列:遥控车[字符串+高精+二分答案]

    [问题描述] 平平带着韵韵来到了游乐园,看到了n辆漂亮的遥控车,每辆车上都有一个唯一的名字name[i].韵韵早就迫不及待地想玩名字是s的遥控车.可是韵韵毕竟还小,她想象的名字可能是一辆车名字的前缀( ...

  8. 够快网盘支持与iOS-ASIHTTPRequest框架学习

    够快网盘支持与iOS-ASIHTTPRequest框架学习 前段时间在公司的产品中支持了够快网盘,用于云盘存储. 在这个过程中,学习到了很多新的知识,也遇到了很多问题,在此记录一下. 首先就够快的AP ...

  9. How To Configure Logging And Log Rotation In Apache On An Ubuntu VPS

    Introduction The Apache web server can be configured to give the server administrator important info ...

  10. Varint code

    Varint编码   LevelDB内部通过采用变长编码,对数据进行压缩来减少存储空间,采用CRC进行数据正确性校验.下面就对varint编码进行学习. 传统的integer是以32位来表示的,存储需 ...