angular 指令的学习

栏目: 编程语言 · AngularJS · 发布时间: 5年前

内容简介:在开发alice项目中,使用了阿里的ng-zorro框架,所以会经常遇到很多框架自己写的属性,例如下面的栅格:其中的nz-row,nz-col,以及nzSpan就是框架自定义的html属性,但他们究竟是什么,又是怎么实现的,我却从来没有想过,所以,趁着本周学习时间比较充裕,就去探索了一下。首先,在webstorm通过

前言

在开发alice项目中,使用了阿里的ng-zorro框架,所以会经常遇到很多框架自己写的属性,例如下面的栅格:

<div nz-row>
    <div nz-col [nzSpan]="4">
        xxx
    </div>
</div>

其中的nz-row,nz-col,以及nzSpan就是框架自定义的html属性,但他们究竟是什么,又是怎么实现的,我却从来没有想过,所以,趁着本周学习时间比较充裕,就去探索了一下。

首先,在webstorm通过 Ctrl + 鼠标点击 nz-col 查看它的源码,如图:

angular 指令的学习

发现nz-col其实是一个指令,就去angular上搜索了指令的内容

一、angular指令概览

在 Angular 中有三种类型的指令:

<yunzhi-data-list></yunzhi-data-list>
nz-row,nz-col
*ngFor,*ngIf

这三种指令中最常用的就是组件,所以我重点学习了后两种指令。

二、属性型指令

自定义属性型指令

目标:使用指令实现给html元素绑定背景色:

<button appHighlight = "yellow">高亮</button>

angular 指令的学习

  1. 生成指令类文件,同生成组件一样,使用CLI命令即可

    ng generate directive highlight

    然后就会多了这两个文件:

    angular 指令的学习

  2. 在指令的逻辑部分:

    export class HighlightDirective implements OnInit {
    // 使用@input绑定传给指令的值
      @Input('appHighlight') highlightColor: string;
      constructor(private el: ElementRef) {    //  ElementRef就是该指令绑定的宿主元素
      }
    
      ngOnInit(): void {
      // 设置该元素的css样式的背景色为输入值
        this.el.nativeElement.style.backgroundColor = this.highlightColor;
      }
    }
  3. 使用该指令:

    <button appHighlight="yellow">高亮</button>
  4. 效果:
    angular 指令的学习
  5. 绑定多个属性:

    export class HighlightDirective implements OnInit {
      @Input('appHighlight') highlightColor: string;
      @Input() defaultColor: string;    // 默认颜色
      constructor(private el: ElementRef) {
      }
    
      ngOnInit(): void {
      // 如果highlightColor有值,则绑定highlightColor,没有则绑定defaultColor
        this.el.nativeElement.style.backgroundColor = this.highlightColor || this.defaultColor;
      }
    }
  6. 使用:

    <button appHighlight="yellow" defaultColor="red">高亮</button>

    angular 指令的学习

    <button appHighlight defaultColor="red">高亮</button>

    angular 指令的学习

selector:选择器

如果我写的指令不想被人乱用,比如上述指令我只想在button中生效,就要用到指令的选择器( selector

)了。

一般我们命令生成指令文件后会有如下默认的代码段:

@Directive({
  selector: '[appHighlight]'
})

这个selector里的字符串就是我们使用指令绑定到宿主元素的规则,或者说实例化指令对象的规则。

angular文档提供的规则表如下:

  • element-name:根据元素名选取。
  • .class:根据类名选取。
  • [attribute]:根据属性名选取。
  • [attribute=value]:根据属性名和属性值选取。
  • :not(sub_selector):只有当元素不匹配子选择器 sub_selector 的时候才选取。
  • selector1, selector2:无论 selector1 还是 selector2 匹配时都选取。

例如,默认的绑定方法就是把该指令当成属性,如: <button appHighlight>高亮</button>

如果我想只绑定给button,就可以这样写:

@Directive({
  selector: '[appHighlight] button'
})

这样一来,当我绑定到其他元素时,编译器就会报错:

angular 指令的学习

如果我不想使用默认的指令前缀 app ,而是换成其他的,如 yunzhi ,则如图修改 tslint.json 文件

angular 指令的学习

修改后:

{
    "extends": "../tslint.json",
    "rules": {
        "directive-selector": [
            true,
            "attribute",
            "yunzhi",
            "kebab-case"
        ],
        "component-selector": [
            true,
            "element",
            "app",
            "kebab-case"
        ]
    }
}

指令选择器也修改前缀:

@Directive({
  selector: '[yunzhi-highlight] button'
})

使用指令:

<button yunzhi-highlight>高亮</button>

三、结构型指令

自定义结构型指令

目标:编写一个 yunzhiUnless 指令,作用与ngIf相反,当变量值为false,显示宿主元素,为true则移除不显示。

<p *yunzhiUnless="condition">测试-p</p>

angular 指令的学习

  1. 首先为了让指令更符合官方的规范,推荐在 tsLint.json 指令选择器使用格式修改为 cameCase ,即默认设置

    "directive-selector": [
         true,
         "attribute",
         "yunzhi",
         "camelCase"
     ]
    @Directive({
      selector: '[yunzhiUnless]'
    })
  2. 新建指令 unless ,注入TemplateRef,ViewContainerRef(没懂下面这句话,先跟着往下写就行)

    使用TemplateRef取得 <ng-template> 的内容,并通过ViewContainerRef来访问这个视图容器

    export class UnlessDirective {
         constructor(private viewContainer: ViewContainerRef,
                 private templateRef: TemplateRef<any>) { }
     
     }
  3. 使用@Inout将一个布尔值绑定到 yunzhiUnless 属性上,当condition为false,显示,为true,不显示

    @Input()
      set yunzhiUnless(condition: boolean) {
        if (!condition) {
          this.viewContainer.createEmbeddedView(this.templateRef);
        } else if (condition) {
          this.viewContainer.clear();
        }
      }
  4. 在模板中使用该指令

    <p *yunzhiUnless="condition">测试-p</p>
  5. 测试指令

    html:

    <p>
      condition={{condition | json}}
    </p>
    
    <label for="show">显示</label>
    <input id="show" type="radio" [value]="false" [(ngModel)]="condition">
    <label for="unshow">不显示</label>
    <input id="unshow" type="radio" [value]="true" [(ngModel)]="condition">
    
    <p *yunzhiUnless="condition">测试-p</p>

    ts:

    export class TestComponent {
      condition = false;
    }

效果:

angular 指令的学习

TemplateRef

如名字所示,TemplateRef 用于表示 模板的引用 ,但我们注意到这里并没有使用 ng-template ,为什么还能引用它呢?

这是因为 *yunzhiUnless 其实是一个语法糖

<p *yunzhiUnless="condition">测试-p</p>

等同于:

<ng-template [yunzhiUnless]="condition">
  <p>测试-ng-template</p>
</ng-template>

如果没有使用结构型指令,而仅仅把一些别的元素包装进 <ng-template> 中,那些元素就是不可见的。

ViewContainerRef

ViewContainerRef 用于表示容器的引用,通常是span,div等

ViewContainerRef 对象提供了 createEmbeddedView() 方法,该方法接收 TemplateRef 对象作为参数,并将模板中的内容作为容器 (comment 元素) 的兄弟元素,插入到页面中。

简单理解就是如下图, templateRef 指向 ng-template 标签, viewContainer 指向 ng-container 标签

angular 指令的学习

总结

简单的了解了angular指令的实现后,发现在使用时减少了很多迷茫,有些以前不懂的细节也知道了为什么会这样,不过也发现自己还有好多不懂的地方,比如模板和容器,DOM的一些操作等。


以上所述就是小编给大家介绍的《angular 指令的学习》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

PHP Cookbook

PHP Cookbook

Adam Trachtenberg、David Sklar / O'Reilly Media / 2006-08-01 / USD 44.99

When it comes to creating dynamic web sites, the open source PHP language is red-hot property: used on more than 20 million web sites today, PHP is now more popular than Microsoft's ASP.NET technology......一起来看看 《PHP Cookbook》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

MD5 加密
MD5 加密

MD5 加密工具