angular4 结构型指令 属性型指令总结

来源:互联网 发布:惠普win10 网络唤醒 编辑:程序博客网 时间:2024/06/03 17:41
属性型指令总结
            看了几次官网的属性指令文档,对一些关键的东西还是很混淆,学到的都是基于表面的使用,这里是我把一些重要的东西给总结起来,方便自己看:

           1.三种指令:组件 、结构型指令(ngif  ngfor等)和属性型指令 (所有组件都为指令)
           结构型指令 —   通过添加和移除 DOM 元素改变 DOM 布局的指令
           属性型指令 —   改变元素、组件或其它指令的外观和行为的指令。

           2.angular在数组元素上发现我们自定义的属性,就是实例化这个指令类,这就意味着我们在模板中引入这个指令,不用像服务一样在构造函数里声明了,按我理解 组件 指令 管道 是处于同一等级的,这样就不存在谁引入谁,直接拿来用就是了。

         3.使用数据绑定向指令传递值
       使用@input 向指令传递值,
           <p appHightlight highlightColor="yellow">Highlighted in yellow</p>
           <p appHightlight [highlightColor]="'orange'">Highlighted in orange</p>
        注意这二者的区别@input向指令输入值的方式不同,多了个[ ]时orange也多了个‘ ’,因为不加orange会当成一个类的属性
        
        4.绑定到第二个属性
          可以直接写在宿主里<p [appHighlight]="color"defaultColor="violet">不过也需要通过@input来接值
         
        5.这个是要注意的为什么要加@Input?

           @Input装饰器都告诉Angular,该属性是公共的,并且能被父组件绑定。 如果没有@Input,Angular就会拒绝绑定到该属性。

但我们以前也曾经把模板HTML绑定到组件的属性,而且从来没有用过@Input。 差异何在?

差异在于信任度不同。 Angular把组件的模板看做从属于该组件的。 组件和它的模板默认会相互信任。 这也就是意味着,组件自己的模板可以绑定到组件的任意属性,无论是否使用了@Input装饰器。

但组件或指令不应该盲目的信任其它组件或指令。 因此组件或指令的属性默认是不能被绑定的。 从Angular绑定机制的角度来看,它们是私有的,而当添加了@Input时,它们变成了公共的 只有这样,它们才能被其它组件或属性绑定。

你可以根据属性名在绑定中出现的位置来判定是否要加@Input。
当它出现在等号右侧的模板表达式中时,它属于模板所在的组件,不需要@Input装饰器。(数据源)
当它出现在等号左边的方括号([ ])中时,该属性属于其它组件或指令,它必须带有@Input 装饰器。(因为angular操作的是dom的property 不是attribute 对不存在的dom属性就不信任,所以有的不需要@input)
试用此原理分析下列范例:
src/app/app.component.html (color)
 content_copy
<p [appHighlight]="color">Highlight me!</p>
color属性位于右侧的绑定表达式中,它属于模板所在的组件。 该模板和组件相互信任。因此color不需要@Input装饰器。
myHighlight属性位于左侧,它引用了MyHighlightDirective中一个带别名的属性,它不是模板所属组件的一部分,因此存在信任问题。 所以,该属性必须带@Input装饰器。



   二 结构型指令
    结构型指令的职责是HTML布局。 它们塑造或重塑DOM的结构,比如添加、移除或维护这些元素。Angular会解开这个*语法糖,变成一个<ng-template>标记,包裹着宿主元素及其子元素

    1.NgIf 大驼峰为类,小驼峰为它的属性。
当我们隐藏掉一个元素时,组件的行为还在继续 —— 它仍然附加在它所属的DOM元素上, 它也仍在监听事件。Angular会继续检查哪些能影响数据绑定的变更。 组件原本要做的那些事情仍在继续。
虽然不可见,组件及其各级子组件仍然占用着资源,而这些资源如果分配给别人可能会更有用。 在性能和内存方面的负担相当可观,响应度会降低,当然,从积极的一面看,重新显示这个元素会非常快。 组件以前的状态被保留着,并随时可以显示。 组件不用重新初始化 —— 该操作可能会比较昂贵。 这时候隐藏和显示就成了正确的选择。
但是,除非有非常强烈的理由来保留它们,否则我们更倾向于移除用户看不见的那些DOM元素,并且使用NgIf这样的结构型指令来收回用不到的资源。    
      
      *ngIf指令被移到了<ng-template>元素上。在那里它变成了一个属性绑定[ngIf]。
        <div>上的其余部分,包括它的class属性在内,移到了内部的<ng-template>元素上。(只会显示最终的结果)
     2、ngfor
         <div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd"> ({{i}}) {{hero.name}}</div>(三种用法)
    <ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById"><div [class.odd]="odd">({{i}}) {{hero.name}}</div></ng-template>
    3.ngswitch 为属性型指令  ngswitchcase 为结构型指令

 三 自定义结构型指令 ng-template
    优先使用星号(*)语法
 星号(*)语法比不带语法糖的形式更加清晰。 如果找不到单一的元素来应用该指令,可以使用<ng-container>作为该指令的容器。
 虽然很少有理由在模板中使用结构型指令的属性形式和元素形式,但这些幕后知识仍然是很重要的,即:Angular会创建<ng-template>,还要了解它的工作原理。 当需要写自 己的结构型指令时,我们就要使用<ng-template>,<ng-template>是一个 Angular 元素,用来渲染HTML。 它永远不会直接显示出来。 事实上,在渲染视图之前,Angular 会把<ng-template>及其内容替换为一个注释。自己写一些标签在ng-template时,不显示当成注释

    四、<ng-container> 的救赎
另一个问题是:有些HTML元素需要所有的直属下级都具有特定的类型。 比如,<select>元素要求直属下级必须为<option>,那么我们就没办法把这些选项包装进<div>或<span>中。  <span *ngFor="let h of heroes">
      <span *ngIf="showSad || h.emotion !== 'sad'">
      <option [ngValue]="h">{{h.name}} ({{h.emotion}})</option>
      </span>
option为空结构指令的错乱

      Angular的<ng-container>是一个分组元素,但它不会污染样式或元素布局,因为 Angular 压根不会把它放进 DOM 中。
      <ng-container *ngIf="hero">
    <option [ngValue]="h">{{h.name}} ({{h.emotion}})</option>
     </ng-container>解决一些标签不显示的问题 (select option)


         杂项:
      1. ElementRef是一个服务,它赋予我们通过它的nativeElement属性直接访问 DOM 元素的能力。 Renderer服务允许通过代码设置元素的样式
      2.@HostListener装饰器引用属性型指令的宿主元素 相当于addEventListene
           当然,你可以通过标准的JavaScript方式手动给宿主 DOM 元素附加一个事件监听器。 但这种方法至少有三个问题:
           必须正确的书写事件监听器。当指令被销毁的时候,
           必须拆卸事件监听器,否则会导致内存泄露。
            必须直接和 DOM API 打交道,应该避免这样做。
    3.@inpout取别名@Input('appHighlight') highlightColor: string;
    4. 每个宿主元素上只能有一个结构型指令,  有一个简单的解决方案:把*ngIf放在一个"容器"元素上,再包装进 *ngFor 元素。 这个元素可以使用ng-container,以免引入一个新的HTML层级
   5.使用TemplateRef取得<ng-template>的内容,并通过ViewContainerRef来访问这个视图容器。 

总结:
结构型指令可以操纵 HTML 的元素布局。
当没有合适的容器元素时,可以使用<ng-container>对元素进行分组。
Angular 会把星号(*)语法解开成<ng-template>。
内置指令NgIf、NgFor和NgSwitch的工作原理。
微语法如何展开成<ng-template>。
写了一个自定义结构型指令 —— UnlessDirective。
angular默认是单数据绑定   angularjs默认是双数据绑定  。 属性指令意味着标签的左右都为组件的属性 。
原创粉丝点击