Angular自定义指令

Angular自定义指令

我是上帝可爱多
2017.07.20 15:18* 字数 560 阅读 420 评论 0
新建一个firstDirective.ts 文件 内容如下
import { Directive, ElementRef, Input } from '@angular/core';

@Directive({'selector':[first]})
export class firstDirective{
      constructor(el:ElementRef){
          el.style.color = 'pink'
          el.style.background = 'green'
}
}

上面我们定义了一个指令,如何调用呢

src/app/app.component.html
<h1>My First Attribute Directive</h1>
<p first>Highlight me!</p>

src/app/app.component.ts
import { Component } from ‘@angular/core’;
@Component({
selector: ‘my-app’,
templateUrl: ‘./app.component.html’
})
export class AppComponent {
color: string;
}

这个时候我们已经把这个指令应用到了组件上,p标签背景色为绿色,文字是pink色。
结束了吗?没有,还有很重要的一步

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { HighlightDirective } from './highlight.directive';
@NgModule({
  imports: [ BrowserModule ],
  declarations: [
    AppComponent,
    HighlightDirective
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

我么需要在模块的 declarations中引入他,这样在该模块下的组件都需要再重新引入了。

就这么简单吗,我们想尝试点难得

src/app/app.component.html
<h1>My First Attribute Directive</h1>

<h4>Pick a highlight color</h4>
<div>
<input type=“radio” name=“colors” (click)=“color=‘lightgreen’”>Green
<input type=“radio” name=“colors” (click)=“color=‘yellow’”>Yellow
<input type=“radio” name=“colors” (click)=“color=‘cyan’”>Cyan
</div>
<p [myHighlight]=“color”>Highlight me!</p>

<p [myHighlight]=“color” defaultColor=“violet”>
Highlight me too!
</p>

我们把页面改成了这样,这是要干嘛,还有2个指令都加了中括号?

import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
selector: ‘[myHighlight]’
})
export class HighlightDirective {

constructor(private el: ElementRef) { }
//注意这2个位置的@input的写法
@Input() defaultColor: string;

@Input(‘myHighlight’) highlightColor: string;

@HostListener(‘mouseenter’)
onMouseEnter() {
this.highlight(this.highlightColor || this.defaultColor || ‘red’);
}

@HostListener(‘mouseleave’)
onMouseLeave() {
this.highlight(null);
}

private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}

从这里我们又发现了一个有趣的事情 p [myHighlight]="color">Highlight me! /p
指令居然也可以放在中括号里面,这样就可以作为父组件传递过来的值。
@HostListener('mouseenter') 监听组件mouseenter事件,当鼠标移上去的时候,点亮。

需要注意一点的是,如果子组件的属性名与父组件上一致时,@input()括号里面可以不写

接下来我们我们玩点花样,修改一下指令文件

import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
selector: ‘div[myHighlight]’
})
export class HighlightDirective {

constructor(private el: ElementRef) { }

@Input() defaultColor: string;

@Input(‘myHighlight’) highlightColor: string;

//我们在这里加了一个 [‘ e v e n t . t a r g e t ′ ] 这 个 必 须 加 不 然 b t n 找 不 到 &lt; / s p a n &gt; &lt; s p a n c l a s s = &quot; h l j s − m e t a &quot; &gt; @ H o s t L i s t e n e r &lt; / s p a n &gt; ( &lt; s p a n c l a s s = &quot; h l j s − s t r i n g &quot; &gt; ′ m o u s e e n t e r ′ &lt; / s p a n &gt; , [ &lt; s p a n c l a s s = &quot; h l j s − s t r i n g &quot; &gt; ′ event.target&#x27;] 这个必须加 不然btn找不到&lt;/span&gt; &lt;span class=&quot;hljs-meta&quot;&gt;@HostListener&lt;/span&gt;(&lt;span class=&quot;hljs-string&quot;&gt;&#x27;mouseenter&#x27;&lt;/span&gt;, [&lt;span class=&quot;hljs-string&quot;&gt;&#x27; event.target]btn</span><spanclass="hljsmeta">@HostListener</span>(<spanclass="hljsstring">mouseenter</span>,[<spanclass="hljsstring">event.target’])
onMouseEnter(btn: HTMLElement) {
btn.style.color = ‘green’
this.highlight(this.highlightColor || this.defaultColor || ‘red’);
}

@HostListener(‘mouseleave’) onMouseLeave() {
this.highlight(null);
}

private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}

上面我们通过了btn来控制样式,所以有:
btn = this.el.nativeElement 指向的是当前指令的宿主。。。
@Directive({
selector: 'div[myHighlight]'
}) 这个意思是说 这个指令只能用在div标签上

我们再来看一个新鲜的

import { Directive, HostBinding, HostListener } from '@angular/core';

@Directive({
selector: ‘[exeButtonPress]’
})
export class ExeButtonPress {
@HostBinding(‘attr.role’) role = ‘button’;
@HostBinding(‘class.pressed’) isPressed: boolean;

<span class="hljs-meta">@HostListener</span>(<span class="hljs-string">'mousedown'</span>) hasPressed() {
    <span class="hljs-keyword">this</span>.isPressed = <span class="hljs-keyword">true</span>;
}
<span class="hljs-meta">@HostListener</span>(<span class="hljs-string">'mouseup'</span>) hasReleased() {
    <span class="hljs-keyword">this</span>.isPressed = <span class="hljs-keyword">false</span>;
}

}

我们又加入了一个新东西 HostBinding,这个东西又是干嘛的呢
1.@HostBinding('attr.role') role = 'button'; 所有的指令宿主元素都会有一个role属性,值为‘button’
2.@HostBinding('class.pressed') isPressed: boolean; 所有宿主元素在按下去的时候会有pressed类

我们来升级一个玩一下,控制dom的显示和隐藏

import {Directive, Input, TemplateRef, ViewContainerRef} from "@angular/core";
@Directive({
  selector:'[myUnless]'
})
export class MyUnlessDirective{
  //从宿主元素获取myUnless值  注入到newCondition
  @Input('myUnless')
  set condition(newCondition:boolean){
    if(!newCondition){
      this.viewContainer.createEmbeddedView(this.templateRef);
      console.log(newCondition);
    }else {
     // 若boolValue为true 删除该宿主元素
      this.viewContainer.clear();
      console.log("clear");
    }
  }
  constructor(
    private templateRef:TemplateRef<any>,
    private viewContainer:ViewContainerRef
  ){}

}

/1
<p *myUnless=“boolValue”>
false
</p>
//2
<p *myUnless="!boolValue">
true
</p>

如果boolValue是false,那么第一个p就会在Dom中显示

接下来我就原创一个悬浮提示的指令

import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
selector: ‘div[tooltip]’
})
export class tooltipDirective {

constructor(private el: ElementRef) { }

@Input(‘myHighlight’) highlightColor: string;

//我们在这里加了一个 [‘ e v e n t . t a r g e t ′ ] 这 个 必 须 加 不 然 b t n 找 不 到 &lt; / s p a n &gt; @ H o s t L i s t e n e r ( &lt; s p a n c l a s s = &quot; h l j s − s t r i n g &quot; &gt; ′ m o u s e e n t e r ′ &lt; / s p a n &gt; , [ &lt; s p a n c l a s s = &quot; h l j s − s t r i n g &quot; &gt; ′ event.target&#x27;] 这个必须加 不然btn找不到&lt;/span&gt; @HostListener(&lt;span class=&quot;hljs-string&quot;&gt;&#x27;mouseenter&#x27;&lt;/span&gt;, [&lt;span class=&quot;hljs-string&quot;&gt;&#x27; event.target]btn</span>@HostListener(<spanclass="hljsstring">mouseenter</span>,[<spanclass="hljsstring">event.target’])
onMouseEnter(btn: HTMLElement) {
btn.style.color = ‘green’
let content = btn.getAttribute(‘content’)
let tooltip = document.createElement(‘div’)
tooltip.innerHTML = content
tooltip.style.position = ‘absolute’
//需要计算出离父元素左边的距离
let left = (parseInt(btn.style.left) - tooltip.offsetwidth)/2
tooltip.style.left = left + ‘px’
btn.appendChild(tooltip)
this.highlight(this.highlightColor || this.defaultColor || ‘red’);
}

@HostListener(‘mouseleave’) onMouseLeave() {
// 当从宿主元素离开时 直接删除该节点就是
this.el.nativeElement.removeChild(tooltip)
this.highlight(null);
}

private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}

好了,今天指令就讲到这里,大家可以看下好好吸收,下回我会讲angular的路由和表单等。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Angular 中,你可以通过自定义指令来扩展 HTML 元素的行为和功能。下面是自定义指令的基本步骤: 1. 创建指令类: - 创建一个新的类,用于定义你的指令。 - 使用 `@Directive` 装饰器来标记该类为一个指令,并传入一个配置对象。 下面是一个示例: ```typescript import { Directive, ElementRef } from '@angular/core'; @Directive({ selector: '[appCustomDirective]' }) export class CustomDirective { constructor(private elementRef: ElementRef) { this.elementRef.nativeElement.style.backgroundColor = 'yellow'; } } ``` 在上面的示例中,我们创建了一个名为 `CustomDirective` 的指令类,并使用 `@Directive` 装饰器来标记它为一个指令。`selector` 属性指定了该指令在模板中的使用方式,这里使用的是属性选择器 `[appCustomDirective]`。 2. 在模板中应用指令: - 在需要应用指令的元素上使用指令的选择器,可以是属性选择器、类选择器或标签选择器。 下面是一个示例: ```html <div appCustomDirective>Custom Directive Example</div> ``` 在上面的示例中,我们使用 `[appCustomDirective]` 属性选择器将自定义指令应用到了 `<div>` 元素上。 3. 使用指令提供的功能: - 在指令类中可以定义各种功能,如修改元素样式、监听事件、操作 DOM 等。 - 在构造函数中可以注入依赖,如 `ElementRef` 用于操作元素。 在上面的示例中,我们在指令类的构造函数中注入了 `ElementRef`,使用它来获取指令所应用的元素,并修改其背景颜色为黄色。 通过以上步骤,你就可以创建和使用自定义指令了。可以根据需求在指令类中实现各种功能,并在模板中应用指令来扩展元素的行为和功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值