如何把Angular自定义Directive的变量绑定到关联Component
实现Angular自定义指令与宿主组件的变量绑定
第一步:改造MovableDirective,对外暴露需要同步的变量
你需要给指令中要传递给组件的属性添加@Output()事件发射器,在属性更新时主动向宿主组件推送最新值。你现有的@Input('appMovable')已经可以支持组件向指令传入布尔类型的开关状态,如果需要双向绑定可以补充对应输出事件。
改造后的指令核心代码如下:
// 导入新增的Output、EventEmitter import { Directive, Input, Output, EventEmitter, ElementRef, HostBinding, HostListener } from '@angular/core'; import { DomSanitizer, SafeStyle } from '@angular/platform-browser'; import { DraggableDirective } from '../draggable/draggable.directive'; import { Position } from '../../../../interfaces/draggable-system/move-position'; @Directive({ selector: '[appMovable]', // 如果需要通过模板引用直接获取指令实例,新增下面这行配置 exportAs: 'appMovable' }) export class MovableDirective extends DraggableDirective { @Input('appMovable') set movable(movable: boolean) { this.enabled = movable; // 若需要双向绑定movable状态,更新时推送最新值 this.appMovableChange.emit(movable); } // movable状态的双向绑定输出事件 @Output() appMovableChange = new EventEmitter<boolean>(); @HostBinding('class.moving') moving = false; // moving状态更新事件 @Output() movingChange = new EventEmitter<boolean>(); position: Position = { x: 0, y: 0 }; // 坐标更新事件,实时推送最新坐标到组件 @Output() positionChange = new EventEmitter<Position>(); private startPosition: Position; private reset = false; constructor( public element: ElementRef, private sanitizer: DomSanitizer) { super(); } @HostBinding('style.transform') get transform(): SafeStyle { return this.sanitizer.bypassSecurityTrustStyle( `translateX(${this.position.x}px) translateY(${this.position.y}px)` ); } @HostListener('dragStart', ['$event']) onDragStart(event: PointerEvent): void { this.moving = true; // 推送拖拽开始状态 this.movingChange.emit(this.moving); this.startPosition = { x: event.clientX - this.position.x, y: event.clientY - this.position.y }; } @HostListener('dragMove', ['$event']) onDragMove(event: PointerEvent): void { this.position = { x: event.clientX - this.startPosition.x, y: event.clientY - this.startPosition.y, }; // 拖拽过程中实时推送最新坐标 this.positionChange.emit(this.position); } @HostListener('dragEnd') onDragEnd(): void { this.moving = false; // 推送拖拽结束状态 this.movingChange.emit(this.moving); if (this.reset) { this.position = { x: 0, y: 0, }; // 重置后也推送最新坐标 this.positionChange.emit(this.position); } } }
第二步:在宿主组件中完成变量绑定
1. 组件TS中定义接收变量
import { Position } from '你的Position接口路径'; @Component({ // 你的组件配置 }) export class 你的组件类 { // 控制拖拽开关的布尔变量 isMovable = true; // 接收实时坐标的变量 currentPosition: Position = {x: 0, y: 0}; // 接收拖拽状态的变量 isMoving = false; }
2. 模板中绑定指令事件
如果你需要双向控制movable开关,直接用Angular的双向绑定语法即可:
<div [(appMovable)]="isMovable" (positionChange)="currentPosition = $event" (movingChange)="isMoving = $event" > 可拖拽元素内容 </div> <!-- 你可以直接在模板中读取绑定后的变量 --> <p>当前X坐标:{{currentPosition.x}},Y坐标:{{currentPosition.y}}</p> <p>是否正在拖拽:{{isMoving}}</p> <p>拖拽功能是否开启:{{isMovable}}</p>
如果你只需要单向控制movable开关,不需要接收指令内部修改的开关状态,用单向绑定即可:
<div [appMovable]="isMovable" (positionChange)="currentPosition = $event" > 可拖拽元素内容 </div>
补充:直接获取指令实例的方法
如果你不需要实时监听变更,只想在需要的时候读取指令的所有公开属性,可以通过模板引用直接获取指令实例:
<div appMovable #movableIns="appMovable"> 可拖拽元素 </div> <button (click)="console.log(movableIns.position)">点击获取当前坐标</button>
内容的提问来源于stack exchange,提问作者DrDave96
相关产品推荐
相关产品推荐

