Angular Material拖拽cdkDragConstrainPosition无法访问组件变量问题
问题描述
使用Angular Material CDK Drag and Drop拖拽功能时,需要在cdkDragConstrainPosition钩子方法内实现拖拽元素吸附对齐组件列布局的计算逻辑。方法触发时所有组件级变量访问均返回undefined,执行console.log(this)输出结果为DragRef实例,说明函数this作用域未绑定到当前组件实例,无法正常读取组件属性。
相关代码
模板代码
<div cdkDrag cdkDragBoundary=".drag-boundary" [cdkDragData]="{'colwidth': colWidth}" [cdkDragConstrainPosition]="computeDragRenderPos" [style.width.px]="colWidth" style="position: absolute; transform: translate3d(80px, 177px, 0px); background-color: beige; top: 0; left: 0; height: 42px; overflow: hidden" > <div>Chris's awesome presentation. Doing fun stuff with science</div> </div>
组件代码
computeDragRenderPos(pos, dragRef, clientRect) { console.log(this); // 输出DragRef实例,而非组件实例 console.log(this.myComponentVariable); // 输出undefined }
解决方案
出现这个问题的核心原因是:普通类方法的this是调用时动态绑定的,CDK内部调用cdkDragConstrainPosition传入的函数时,会将上下文指向内部的DragRef实例,不会自动绑定组件实例。可通过以下方式解决:
- 方案1(推荐):将方法改为箭头函数形式的类属性。箭头函数不会生成自身的
this上下文,会直接继承类实例化时的组件上下文,不会被调用方改写。import { Point, DragRef } from '@angular/cdk/drag-drop'; // 组件类内定义方法 computeDragRenderPos = (pos: Point, dragRef: DragRef, clientRect: DOMRect): Point => { // 此处this指向当前组件实例,可正常访问所有组件级变量 console.log(this.myComponentVariable); const colWidth = this.colWidth; // 实现列吸附逻辑:按列宽取整对齐 const alignedX = Math.round(pos.x / colWidth) * colWidth; return { x: alignedX, y: pos.y // 纵向如果不需要吸附可直接返回原坐标 }; } - 方案2:模板绑定时手动绑定
this上下文。该方式不需要修改方法定义,但注意不要在模板中重复调用bind产生不必要的性能开销。<!-- 模板中修改绑定写法 --> [cdkDragConstrainPosition]="computeDragRenderPos.bind(this)" - 补充方案:如果只需要读取提前传入
cdkDragData的数据,不需要访问其他组件变量,也可以直接从入参dragRef上读取挂载的数据,不需要处理this绑定:computeDragRenderPos(pos, dragRef, clientRect) { const colWidth = dragRef.data.colwidth; // 直接读取cdkDragData传入的列宽 // 后续计算逻辑 }
内容的提问来源于stack exchange,提问作者Chris Kooken
相关产品推荐
相关产品推荐

