最近一段时间准备使用AngularJs中的自定义Directive重构一下代码。

在这里说明一下,把自定义控件封装成Directive并不一定是要复用,而是要让代码结构更加清晰。就好像你将一个长方法拆分成多个独立的小方法,也未必要复用它们一样。职责独立等一票好处,会让后期维护更加轻松。

在重构的过程中,我遇到了这样一个问题,先上图:

图一:

这就是我要重构的界面,由于之前时间紧,将这三个Filter和两个button都写在了一个页面中。当时我已经预感到,如果将这里面的状态都写到一个scope上,将出现后期近乎不可维护的灾难。尽管我已经将它们用ViewModel隔离,但代码结构依然让我很不满意。

你说啥?没看出来哪复杂。好,你等着,接下来让你看看里面啥样。

图二:

这是其中一个下拉框展开的模样。什么?你觉得这很一般呐?没看出它多么狰狞?好,你等着。上图三。

图三:

这是三哥展开之后的完全体。现在你应该明白将它们封装成directive是多么必要。

(上图中的这个产品是如今风靡全球的DocAveOnline,使用微软SharePoint的公司没有不知道的。啥?你没听过?偶,忘了说了,只有大公司才用得上)

我重构的思路很简单,将每一个下拉框都独立写成一个directive,然后将哥仨嵌入同一个Directive中,这个外层的directive里面包含Filter和Reset两个Button。

这里原本的交互逻辑是这样的,每个下拉框中的元素都有自己的初始化状态。但是不论你之前怎么霍霍,点击那个Reset按钮之后,要恢复每个下拉框的“出厂设置”。

每个下拉框的Directive拥有独立的scope是肯定的,一切自给自足,与外界无关。也就是说,每个下拉框的reset方法是封装在自己的Directive之中。

那么问题来了,我点击Reset按钮之后,怎么才能调用其子元素中的reset方法?

开始我尝试使用require和link的组合,我是想将reset方法封装到下拉框的controller中,然后在父元素中将三个下拉框对应的directive名字写到require中,这样我就能在父元素的link方法的第四个参数中取到,由这三个子元素controller组成的数组,这我就能轻松调用每个controller的reset方法。(本来controller的作用就是对外暴露API)

可写着写着我就发现不对,好像require只能找自己或者向父元素查找,没法由父元素发起向子元素查找的行动。(也许有,但没找到。如果你知道请在留言中告诉我。)

在江郎才尽的情况下,请教了我师父,他告诉我以下这种方法,其实一点儿都不难,就看你是否理解了自定义directive中,scope里面的,'='这个符号。

稍微懂点儿就知道,这是双向绑定的意思。那解决办法来了,代码如下:

Html部分:

<div ng-controller="myCtrl">
<div>
<inner-directive filter-model="filterModel"></inner-directive>
<button ng-click="filterModel.reset()">click</button>
</div>
</div>

Js部分:

 <script>
  angular.module('app',[])
  .controller('myCtrl',function($scope){
  $scope.filterModel = {
  name:'xiaomablog'
};
    })
.directive('innerDirective',function(){
  return {
  restrict:'E',
scope:{
  filterModel:'='
},
template:'<div ng-bind="filterModel.name"></div>',
link:function(scope,elem,attrs){
  scope.filterModel.reset = function(){
  console.log('reset');
};
}
}
});
</script>

在innerDirective中的scope属性中,定义了filterModel这个双向绑定的属性,这就意味着directive内部可以霍霍这个属性,外部myCtrl中也可以霍霍这个属性,这样的话彼此都能调用对方霍霍的结果。

我贴心地下了断点,debug给你看:

第一步:

Angular的启动过程是先初始化外部的scope,也就是先执行myCtrl中的方法,给filterModel赋了一个对象;

(注意,此刻filterModel的值为undefined)

第二步:

(没添加reset方法之前,已经看到了之前加的name属性)

然后才执行directive的link方法,将scope与DOM紧紧地联系在一起。

第三步:

此时点击button,已经能调用reset方法了,并在console中打印出'reset'

大家可以尝试在myCtrl和innerDirective的link方法中加断点debug一下,亲自观察执行顺序,加深印象。

注意:

      我们了解锤子的方式 , 不是盯着它看 , 而是拿起来用。

                  —— 马丁·海德格尔

听马丁的话,赶紧去敲。

AngularJs中,如何在父元素中调用子元素为自定义Directive中定义的函数?的更多相关文章

  1. IE6滤镜在实战测试中能让父层里面的子元素产生阴影

    1.写法一: <div class="cornerbg">    <p class="title-file">------</p& ...

  2. jquery层级原则器(匹配父元素下的子元素)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. 【IE6的疯狂之十】父级使用padding后子元素绝对定位的BUG

    在前端开发中,经常会用到css的position:absolute来使层浮动,前通过left,top,right等属性来对层进行定位,但ie6对left,top,right等属性的解释和ie7,ie8 ...

  4. CSS实现父元素半透明,子元素不透明

    CSS实现父元素半透明,子元素不透明. 很久以来大家都习惯使用opacity:0.5在新式浏览器里实现半透明,而对IE较旧的版本使用filter:Alpha(opacity=0.5)的滤镜来实现半透明 ...

  5. 【vue】父组件主动调用子组件 /// 非父子组件传值

    一  父组件主动调用子组件: 注意:在父组件使用子组件的标签上注入ref属性,例如: <div id="home"> <v-header ref="he ...

  6. vue父组件如何调用子组件的属性或方法

    常常我们需要组件的拆分,就涉及到父子调用的关系,那么父组件如何调用子组件的属性和方法呢? 子组件child <template> <div> {{msg}} </div& ...

  7. CSS父元素高度随子元素高度变化而变化

    <html> <body> <head> <style> #menu{width:1000px;overfloat:hidden;} /* width: ...

  8. 父元素设置min-height子元素设置100%问题

    问题:父元素设置min-height子元素高度设置100%取不到值,这是因为子元素 div设置 height:100%: 只有当父级元素满足min-height:1000px;设置的条件才触发: 浏览 ...

  9. AngularJS自定义Directive中link和controller的区别

    在AngularJS中,自定义Directive过程中,有时用link和controller都能实现相同的功能.那么,两者有什么区别呢? 使用link函数的Directive 页面大致是: <b ...

随机推荐

  1. poj1001求幂

    这道题目是实质上就是高精度的乘法,虽然是带小数点的数多少次幂,但是开始我们需要将它变为整数进行求幂,然后再加上小数点,然后要考虑前导0,有效数位问题,做的时候要十分的小心 #include<io ...

  2. 尽量不用char*作为hash_map的key

    引子: 同事前几天用hash_map时发现一些问题.当时的场景是有一些字符串char*,要去对应某种类型的对象.同事的做法是: 尝试用char*作为key进行hash.编译通过,但运行时不正常,ins ...

  3. JBPM4 安装和配置

    安装和配置jBPM4,并举个hello.w   至于网上很复杂,但又不懂的插件,我们先不鸟他. myeclipse8\dropins这里就是给我们放插件的,类似SVN之类的.所以小生也修改了下,共享了 ...

  4. 如何优化运行在webkit上的web app

    如何优化运行在webkit上的web app 近来公司有个web app 项目运行在移动版android系统上,发现在电脑上跑的很流畅的web页面在移动版webkit上非常不流畅.根本无法和nativ ...

  5. .net分页控件简单实现

    .net分页控件简单实现 好久好久没写博客了.....最近写了一个.net的分页控件,放到园子里...你觉得好,就点个赞,不好呢,就告诉我为啥吧.... 是使用Request.QueryString的 ...

  6. 国外大师给PHP初学者的8条建议

    学习一门新语言可能会是一件很艰巨的任务,最好的办法就是借鉴前辈的经验已达到事半功倍,下面就是为php新手们准备的一些经验餐. 1.从OOP开始Naramore是SourceForge员工以及PHPWo ...

  7. 从零开始学C++之对象的使用(二):四种对象生存期和作用域、static 用法总结

    一.四种对象生存期和作用域 栈对象 隐含调用构造函数(程序中没有显式调用) 堆对象 隐含调用构造函数(程序中没有显式调用),要显式释放 全局对象.静态全局对象 全局对象的构造先于main函数 已初始化 ...

  8. Android tools:context=".MainActivity"的作用

    <TextView android:layout_width="wrap_content" android:layout_height="wrap_content& ...

  9. tampermonkey,采用js解析自定义脚本,实现网页列表数据采集分析

    最近一直在做数据采集的事情,目的是使用java开发一套分析指定采集规则,模拟用户动作做数据提取.因此定义了一套动作脚本,open,click,get,list,opentab,closetab...j ...

  10. Influxdb原理详解

    本文属于<InfluxDB系列教程>文章系列,该系列共包括以下 15 部分: InfluxDB学习之InfluxDB的安装和简介 InfluxDB学习之InfluxDB的基本概念 Infl ...