美文网首页angular2与vue的那些事
Angular2 源码解读 - 自定义指令@Directive

Angular2 源码解读 - 自定义指令@Directive

作者: 阿踏 | 来源:发表于2018-04-05 15:28 被阅读2次

    定义
    属性型指令用于改变一个DOM元素的外观或行为

    案例@Directive({ selector : '[highlight]' }) export class HighlightDirective{ constructor( renderer : Renderer, el : ElementRef ){ renderer.setElementStyle(el.nativeElement, 'backgroundColor', 'gold'); console.log( `* AppRoot highlight called for ${el.nativeElement.tagName}`); } }
    详解

    1. 使用@Directive注解
    @Directive({
      selector : '[highlight]'
    })```
    它至少需要一个selector属性用以标志指令的选择对象,selector属性可以有以下几种写法:
    
    写法  选择对象
    element-name    按元素名称选择
    class   按类名称选择
    [attribute] 按属性名称选择
    [attribute] 按属性名称和值选择
    :not(sub_selector)  只有当元素与sub_selector不匹配时才选择
    selector1,selector2 选择selector1或selector2
    这里highlight添加方括号很明显是按属性名称选择。
    
    除此之外Directive指令还经常使用一个host属性。
    
    host : 监听事件或改变行为,为一个key和value都为string类型的对象集
    
    例子
    

    @Directive({
    selector: 'button[counting]',
    host: {
    '(click)': 'onClick($event.target)'
    }
    })
    class CountClicks {
    numberOfClicks = 0;

    onClick(btn) {
        console.log("button", btn, "number of clicks:", this.numberOfClicks++);
    }
    

    }

    @Component({
    selector: 'app',
    template: <button counting>Increment</button>
    })
    class App {}```
    监听事件时,事件名使用()包裹,执行方法处于指令内部类中,并加()以标识运行,可以传递$event相关的属性,但方法执行完成返回false时,该事件将被停止冒泡。

    除了监听事件,还可以改变指令的其它属性,例如添加class,例:

    host : {
        '[class.bg-red]' : 'true',
        '[class.color-black]' : 'colorBlack'
    }```
    那么上面,首先bg-red类值为true,它会被添加到指令所在的选择器上,而color-black则绑定了一个值,这个值同样在指令内部类中定义,可以使用简单的
    
    colorBlack = false;
    让color-black类不被添加,也可以使用getter方式:
    
    ```get colorBlack {
        return false;
    }```
    达到同样的目的。如果没有定义,默认为false
    
    当然,使用host直接定义属性也是可以的
    

    host : {
    'myAttribute' : 'cmx'
    }```
    如果综合使用,假如想让一个DOM点击之后,添加点击过的类样式,可以这样:

    host : {
        [class.isClicked] : 'isClicked',
        '(click)' : 'clickIt()'
    }
    
    ...
    
    {
        isClicked : boolean = false;
        
        clickIt(){
            this.isClicked = true;
        }
    }```
    >2. 注入DOM操作相关依赖
    
    正如案例所示,指令的构造函数注入了两个对象,Renderer和ElementRef。
    
    Renderer是angular提供的渲染相关api集:
    

    export declare abstract class Renderer {
    abstract selectRootElement(selectorOrNode: string | any, debugInfo?: RenderDebugInfo): any;
    abstract createElement(parentElement: any, name: string, debugInfo?: RenderDebugInfo): any;
    abstract createViewRoot(hostElement: any): any;
    abstract createTemplateAnchor(parentElement: any, debugInfo?: RenderDebugInfo): any;
    abstract createText(parentElement: any, value: string, debugInfo?: RenderDebugInfo): any;
    abstract projectNodes(parentElement: any, nodes: any[]): void;
    abstract attachViewAfter(node: any, viewRootNodes: any[]): void;
    abstract detachView(viewRootNodes: any[]): void;
    abstract destroyView(hostElement: any, viewAllNodes: any[]): void;
    abstract listen(renderElement: any, name: string, callback: Function): Function;
    abstract listenGlobal(target: string, name: string, callback: Function): Function;
    abstract setElementProperty(renderElement: any, propertyName: string, propertyValue: any): void;
    abstract setElementAttribute(renderElement: any, attributeName: string, attributeValue: string): void;
    /**
    * Used only in debug mode to serialize property changes to dom nodes as attributes.
    */
    abstract setBindingDebugInfo(renderElement: any, propertyName: string, propertyValue: string): void;
    abstract setElementClass(renderElement: any, className: string, isAdd: boolean): void;
    abstract setElementStyle(renderElement: any, styleName: string, styleValue: string): void;
    abstract invokeElementMethod(renderElement: any, methodName: string, args?: any[]): void;
    abstract setText(renderNode: any, text: string): void;
    abstract animate(element: any, startingStyles: AnimationStyles, keyframes: AnimationKeyframe[], duration: number, delay: number, easing: string, previousPlayers?: AnimationPlayer[]): AnimationPlayer;
    }```
    api命名清晰明了不过多赘述(感受一下一个好的命名习惯多么关键)
    ElementRef是一个视图中原生元素的封装,它在浏览器中通常是DOM元素。
    它仅有一个nativeElement属性指向这个原生对象。
    权,非商业转载请注明出处。

    相关文章

      网友评论

        本文标题:Angular2 源码解读 - 自定义指令@Directive

        本文链接:https://www.haomeiwen.com/subject/xsgaqftx.html