angularjs的directive的属性含义详解

在介绍directive之前,我想先讲讲MVC这个框架的相关知识。这样可以更好的理解angular。

什么是MVC?mvc是一种设计模式,它把应用划分为三个部分,数据(模型),展现层(视图),控制交互层(控制器),一个时间的发生时这样的过程:

1.用户和应用产生交互

2.控制器的事件处理器被触发

3.控制器从模型中请求数据,并将其交给视图

4.视图将数据呈现给用户。

模型

模型用来存放应用的所有数据对象,模型不必知晓视图和控制器的细节,模型只需包含数据及直接和这些数据相关的逻辑。任何事件处理代码、视图模板,以及那些和模型无关的逻辑都应当隔离在模型之外。将模型和视图的代码混在一起,是违反MVC架构原则的。模型是最应该从你的应用中解耦出来的部分。

当控制器从服务端抓取数据或者创建新的记录时,它就将数据包装成模型实例,也就是说,我们的数据是面向对象的,任何定义在这个数据模型上的函数或者逻辑都可以直接被调用。

因此,不要这样做:  

var user = users["foo"];
destroyUser(user);

  上面的代码没有命名空间的概念,并且不是面向对象的。如果在应用中定义了另一个destoryUser()函数的话,两个函数就会产生冲突。我们应当确保全局变量和函数的个数尽可能少.而要这样做。

var user = User.find("foo");
user.destroy();

  上面的代码中,destory()函数是存放在命名空间User的实例中的。这种代码更加清晰,而且非常容易做继承,类似destory()的这种函数就不用在每个模型中都定义一遍了。

视图

视图层是呈现给用户的,用户与之产生交互,在JavaScript 应用中,视图大都是由HTML、CSS和JavaScript模板组成的。除了模板中简单的条件语句之外,视图不应当包含任何其他逻辑。

这并不是说MVC不允许包含视觉呈现相关的逻辑,只要这部分逻辑没有定义在视图之内即可。我们将视觉呈现逻辑归类为“视图助手”(helper):和视图有关的独立的小型工具函数。

反例——formatDate()函数直接插入视图:

// template.html
<div>
    <script>
        function formatDate(date) {
            /* ... */
        };
    </script>

    ${ formatDate(this.date) }
</div>

  应该这样做——所有视觉呈现逻辑都包含在helper变量中,这是一个命名空间,可以防止冲突并保持代码清晰、可扩展:

  

// helper.js
var helper = {};
helper.formatDate = function(){ /* ... */ };

// template.html
<div>
    ${ helper.formatDate(this.date) }
</div>

  控制器

控制器是模型和视图之间的纽带,控制器从视图获得时间和输入,对它们惊醒处理(很可能包含模型),并相应的跟新视图。当页面加载工作时,控制器会给视图添加事件监听,比如监听表单提交或者按钮点击。然后,当用户和应用产生交互时,控制器中的事件触发器就开始工作了。

下面用jQuery实现一个例子:

var Controller = {};

// 使用匿名函数来封装一个作用域
(Controller.users = function($){

    var nameClick = function(){
        /* ... */
    };

    // 在页面加载时绑定事件监听
    $(function(){
        $("#view .name").click(nameClick);
    });
})(jQuery);

  上面的代码创建了users控制器,这个控制器是放在Controller变量下的命名空间。然后用了一个匿名函数封装了一个作用域,以避免对全局作用域造成污染。当页面加载时,程序给视图元素绑定了点击事件的监听。

上面就是mvc的简单介绍。下面继续directive的属性讲解。

基本上每个directive都会经过$compile编译,然后通过link函数来拓展相应的DOM元素。下面介绍常用的directive定义的对象:

priority

当有多个directive定义在同一个DOM元素上时,有必要指定directive的应用顺序。priority对象通常用数字表示,数字越大的,相应的指定便优先编译,相反该directive对应的link函数便越靠后执行。priority的值默认为是0.

scope(讲到这个,值得提一提$scope对象,还有在controller中使用$scope和this(当在html中使用controller as时可以使用)的区别,感兴趣的话自行搜索)

它的值有三种;true,false(默认),object(对象)。

什么是angular中的scope?

scope(http://code.angularjs.org/1.0.2/docs/api/ng.$rootScope.Scope)是一个指向model的object。也是表达式的的执行上下文(请自行了解执行上下文的概念)。angular中提供了一些常用API:$watch API(http://code.angularjs.org/1.0.2/docs/api/ng.$rootScope.Scope#$watch),用于监测model的变化,$apply API(http://code.angularjs.org/1.0.2/docs/api/ng.$rootScope.Scope#$apply),用于监测angular 定义的对象内外的所有model的变化。

在angular中,子作用域一般是通过原型继承机制继承其父作用域的属性和方法,但是有一个例外:在directive中,使用scope:{...},这种方式创建的作用域是一个独立的(isolate)作用域,它也有父作用域,但父作用域不在其原型链上,不会对父作用域原型继承,这种方式定义作用域通常用于构造可复用的directive组件,因为这样定义的scope,不会直接访问或者时候修改父作用域的属性,不会产生意外的副作用。

如果我们在子作用域中访问一个父作用域中定义的属性,那么程序会首先在子作用域中寻找该属性,没找到在从原型链上的父作用域中寻找,在没找到,再往上一级原型链找。在angular中,作用域原型链的顶端是$rootScope。

在单独的directive中,scope的概念还是比较清晰的。

当scope取值为false时,此时directive没有独立的scope对象,link函数中引用的scope对象为来自于当前节点的默认controller。

当scope取值为true是时,directive拥有独立的scope对象,此scope是由父scope继承而来,可以访问父scope中的所有属性,此时通过javasript原型继承。值得注意的是:当给此scope继承而来的属性名称赋值时,子scope会相应建立一个本地属性,此时改变的是本scope的变量属性,父scope中的属性是不会改变的。

当scope取值为{propertyName:"[email protected]},此时directive拥有一个隔离的scope对象,其实就是一个全新的scope对象,和上面取值的区别就是不能通过原型继承访问父scope中的属性,但是可以通过$parent属性去访问父scope中对象属性的。

下面讲讲当scope取值为{...}时,申明scope对象的引用修饰符的用法:(http://stackoverflow.com/questions/14050195/angularjs-what-is-the-difference-between-and-in-directive-scope)

1.=或者=attr  隔离作用域的属性与父作用域的属性进行双向绑定,任何一方修改都会影响对方,此时指令中的属性取值为controller中对应的$scope上属性的值,这是最常用的方式;

[email protected]或者@attr  此时指令中的属性取值为html中的字面量或者直接量。这样是建立一个local scope property到DOM的property的绑定,因为值总是string类型,故这个值总是返回一个字符串,并且字符串的值永远是从父作用域继承而来的(即只能读取父作用域中属性值,不能修改,属于单向绑定)。如果没有通过@attr指定属性名称,那么本地名称将于DOM的属性一致。例如<widget my-attr=”hello {{name}}”>,widget的scope定义为:{localName:’@myAttr’}。那么,widget scope property的localName会映射出”hello {{name}}"转换后的真实值。name属性值改变后,widget scope的localName属性也会相应地改变(仅仅单向,与上面的”=”不同)。name属性是在父scope读取的(不是组件scope).

3. & or &attr “Isolate”作用域把父作用域的属性包装成一个函数,从而以函数的方式读写父作用域的属性,包装方法是$parse();

controller

这是嵌套directive之间交互的重要属性对象。

套用一个经典定义( what the O‘Reily AngularJS book by the Google Team has to say):Controller - Create a controller which publishes an API for communicating across directives. A good example is Directive to Directive Communication。意即这个controller是用来存放一些可以在各个directive之间的共享的方法。当两个或更多的directive之间需要通信时(即directive A需要用到directive B中的方法M),这时方法M就可以在directive B中的controller对象中来定义这个方法。此时方法M便类似一些公共的API(可以供其他的directive使用。)详情请参考:http://www.cnblogs.com/xing901022/p/4290411.html

这个controller可以注入以下本地变量:

$scope (当前元素作用域),$element(当前元素),$attrs(当前元素的属性对象),$transclude(后面介绍这个变量,感兴趣的自己去谷歌)。

require

这个对象表示需要另外一个directive B(directive之间的通信)并且将会注入directive B所在的controller到linking function中,它的值一般是‘xxxController‘或者‘^xxxController‘,表示这个directive需要使用directive B的controller属性中的API。

restrict

限制directive在html中作用的方式:

‘E‘ element name,表示以元素的形式在html中作用,例如<my-directive></my-directive>

‘A‘ attribute ,表示以属性的方式作用在html中,例如 <div my-directive=‘exp‘></div>

‘C‘ class ,表示以class的形式在html中作用,例如<div class=‘my-directive : exp ;‘></div>

‘M‘ 以注释的方式在html中作用,例如<!-- directive: my-directive exp -->

当然,以上也可以组合使用,表示逻辑and。例如 restrict : ‘EA‘,\

template

模板代替directive的元素的内容(默认),也可以完全代替元素本身(当replace值为true时有效),也可以用来封装directive的元素的内容(当transclude的值为true时有效)。

取值:

  • A string. For example <div red-on-hover>{{delete_str}}</div>.
  • A function which takes two arguments tElement and tAttrs (described in the compile function api below) and returns a string value.

templateUrl

模板加载地址,异步加载。

replace

取值为true时,模板将会取代directive的元素;取值为false,模板将会取代directive的元素的内容。

transclude

一般情况下取值有三种true,‘element‘,{...},通常用到前两种。

当取值为true时, transclude the content (i.e. the child nodes) of the directive‘s element.举个例子:

比如说你有一个申明transclude :true的directive叫做my-transclude-true,如下:

<div>
  <my-transclude-true>
    <span>{{ something }}</span>
    {{ otherThing }}
  </my-transclude-true>
</div>

  当它被编译之后,就会变成如下:

<div>
  <my-transclude-true>
    <!-- transcluded -->
  </my-transclude-true>
</div>

 my-transclude-true这个directive的内容content(子节点),即‘<span>{{something..‘,将在这个directive中 可用。

再比如说你有一个申明transclude :‘element‘的directive叫做my-transclude-element,如下:

<div>
  <my-transclude-element>
    <span>{{ something }}</span>
    {{ otherThing }}
  </my-transclude-element>
</div>

  被编译之后,就会变成如下:

<div>
   <!-- transcluded -->
</div>

  这里,它的整个元素包括它的子节点都将在这个directive中可用。当transclude这个属性被申明为‘element‘时,directive中的template属性将会失去作用。

最后一个重要的属性:link

这个属性只有在compile这个属性未定义时才能使用。

一般的语法糖:link : function (scope,iAttrs,iElement,controller){...}

link function的作用:Programmatically modify resulting DOM element instances, add event listeners, and set up data binding.以编程方式修改生成的DOM元素实例,添加事件监听器,设置数据绑定。这是整个directive逻辑放的最多的地方。

下面说说这个函数的参数含义:

scope  directive用来注册监听事件registering watches的作用域;

iElement  调用这个directive的实例的元素,比如:angular.module(‘app‘,[]).directive(‘myDirective‘,function(...){template :‘<div data=‘data‘><ul></ul></div>‘,replace:true});这个directive的元素就是‘<div><ul></ul></div>‘,只有在postlink函数中处理元素的子节点‘<ul></ul>‘才是安全的,因为子节点已经被link了。(https://docs.angularjs.org/api/ng/service/$compile #link)

iAttrs 调用这个directive的实例的元素的属性,如上为[data],是一个属性列表集合。

controller:这个diective所需要的controller实例,通常在require这个属性后面已经写明。

以上大概就是平时开发过程中常用到的几个属性。

后面要续写的内容预知:

1.嵌套directive之间的通讯(即directive之间的交互);

2.directive与controller之间的数据传递和通信;

3.controller与controller之间的数据传递和通信。

时间: 2024-08-01 00:52:06

angularjs的directive的属性含义详解的相关文章

js的offsetParent属性用法详解

js的offsetParent属性用法详解:此属性是javascript中较为常用的属性,对于它的良好掌握也是非常有必要的,下面就通过代码实例介绍一下它的用法,希望能够给需要的朋友带来一定的帮助.一.基本介绍:此属性可以返回距离指定元素最近的采用定位(position属性值为fixed.relative或者absolute)父级元素,如果父级元素中没有采用定位的元素,则返回body对象的引用.语法结构: obj.offsetParent 二.代码实例: <!DOCTYPE html> <

offsetleft属性用法详解

offsetleft属性用法详解:本章节通过代码实例介绍一下offsetleft属性的用法,需要的朋友可以做一下参考.此属性可以返回当前元素距离某个父辈元素左边缘的距离,当然这个父辈元素也是有讲究的.(1).如果父辈元素中有定位的元素,那么就返回距离当前元素最近的定位元素边缘的距离.(2).如果父辈元素中没有定位元素,那么就返回相对于body左边缘距离.语法结构: obj.offsetleft 特别说明:此属性是只读的,不能够赋值.代码实例: <!DOCTYPE html> <html&

pointer-events属性值详解

其实早知道这个属性,但是一直没有去研究过.今天正好在twitter看到这个词,就去研究了下,正好解决了目前遇到的一个小难题,所以分享下.嗯,其实这是个比较简单的CSS3属性. 在某个项目中,很多元素需要定位在一个地图层上面,这里就要用到很多绝对定位或者相对定位的元素,但是这样的话,这些浮在上面的div或者其它元素一般都会给个宽高,或者relative的元素可以不给宽高,这个时候,这些元素就会盖住下面的地图层,以至于地图层无法操作... 然后正好在Google map见到了类似的问题,拿来当例子来

CSS3属性transform详解之(旋转:rotate,缩放:scale,倾斜:skew,移动:translate)

CSS3属性transform详解之(旋转:rotate,缩放:scale,倾斜:skew,移动:translate) 在CSS3中,可以利用transform功能来实现文字或图像的旋转.缩放.倾斜.移动这四种类型的变形处理,本文将对此做详细介绍. 一.旋转 rotate 用法:transform: rotate(45deg); 共一个参数"角度",单位deg为度的意思,正数为顺时针旋转,负数为逆时针旋转,上述代码作用是顺时针旋转45度. 二.缩放 scale 用法:transform

CSS3属性选择器详解

上一章在<CSS3基本选择器>中主要介绍了CSS3选择器的第一部分,这节主要和大家一起来学习CSS3选择器的第二部分——属性选择器.属性选择器早在CSS2中就被引入了,其主要作用就是对带有指定属性的HTML 元素设置样式.使用CSS3属性选择器,你可以只指定元素的某个属性,或者你还可以同时指定元素的某个属性和其对应的属性值. 从上一节展示的CSS3选择器的图表中,我们可以知道,CSS3的属性选择器主要包括以下几种: E[attr]:只使用属性名,但没有确定任何属性值: E[attr="

CSS3新增属性text-shadow详解及燃烧的字体实战开发

今天我们有很多程序员在给文本设置样式时,都感觉无从下手.一般有两种情况: 1) 不知道关于文本到底有哪些样式属性: 2) 即使借助开发工具的自动提醒,依然不清楚样式属性的具体意思,以及具体用法. 今天这篇文章,我将带领大家一起来领受CSS3在文本样式应用方面的超强能力.通过精彩的实例,来使大家重新认识CSS3文本样式,真心希望大家通过此篇文章,即使不能做到精通CSS3的文本样式的应用,也会做到熟练应用. 实例: 如何利用CSS3制作燃烧的字体? 以前,如果我们网页上想要显示一个燃烧着的文本,大家

CSS3属性选择器详解 及 双色球实战开发

在前面的章节中,我们了解了,可以使用行内样式,ID选择器,类选择器,以及标签选择器来给一个元素应用样式. 如果我们想给定义了那些都定义了某一个属性的元素应用样式,这个时候我们该怎么做呢? 这一节中,我将使用 双色球案例 和 文档类型提示图标案例 来引入和应用属性选择器. 双色球案例: 大家都知道,双色球共有7个球,6个红球,1个蓝球.首先我们先在页面上面定义7个span标签: <!DOCTYPE html> <html> <head> <meta charset=

objective C 内存管理及属性方法详解

oc为每个对象提供一个内部计数器,这个计数器跟踪对象的引用计数,当对象被创建或拷贝时,引用计数为1,每次保持对象时,调用retain接口,引用计数加1,如果不需要这个对象时调用release,引用计数减1,当对像的引用计数为0时,系统就会释放掉这块内存,释放对象调用dealloc 当对象包含其他对象时,就得在dealloc中自己释放他们 NSObject是IOS所有类的基类 有两个基本函数,alloc和dealloc alloc类似于C++的new,dealloc类似于delete 当对象的re

属性动画详解一(Property Animation)

效果图: Android动画有两类: 1.View Animation(Frame Animation,Tween Animation) 2.Property Animation 其中,上述效果是用第二类属性动画做的. 什么是属性动画? 通俗的说,属性动画就是在一定的时间内,按照一定的规律来改变对象的属性(该属性对于该对象应该是从形态(大小,位置等)上可以感受到的),从而是对象展现出动画的效果. 作用:可以定义动画来改变对象的属性( You can define an animation to