如何在保留内部this上下文的同时获取外部this上下文
问题背景
需要在Grid组件的load普通回调中同时访问两个上下文:
- 回调函数被Grid调用时绑定的
this:指向GridComponent实例,用于获取父行数据、操作Grid自身属性方法 - 外层Angular组件类的实例
this:用于访问类上定义的tools等业务属性
直接用箭头函数定义load会导致Grid无法绑定自身实例到this,用普通函数则无法通过this直接访问外层类实例。
可行解决方案
两种方案都基于闭包缓存外层类实例的思路,不需要修改load函数的普通函数形式,完全兼容Grid组件的this绑定逻辑。
方案1:立即执行箭头函数包裹配置定义(无需调整生命周期逻辑)
在定义childGrid配置时,用立即执行的箭头函数包裹配置返回逻辑:箭头函数没有独立的this,会词法绑定到外层类实例,提前将其缓存到局部变量中,内部的load普通函数通过闭包即可访问该变量,同时自身的this仍可被Grid正常绑定。
export class ToolSelectionComponent implements OnInit { @ViewChild('toolGroupGrid') public grid: GridComponent; public tools: Tool[] = [...]; public toolGroups: { Id: number, Name: string }[] = [...]; public toolsGroupAssignments: { GroupId: number, ToolId: bigint }[] = [...]; public childGrid: GridModel | GridComponent = (() => { // 此处this为外层ToolSelectionComponent类实例,提前缓存 const componentRef = this; return { columns: [...], load() { // 此处this为Grid组件绑定的GridComponent实例,符合组件预期 const grid = this as GridComponent; const groupId = grid.parentDetails.parentRowData['Id']; // 通过闭包访问缓存的外层类实例 grid.dataSource = componentRef.tools.filter(t => t.groupId === groupId); } } })(); ... }
方案2:在生命周期钩子中初始化Grid配置(逻辑更直观)
把childGrid的初始化逻辑移到ngOnInit生命周期中执行:此时类实例已经完成初始化,直接在钩子作用域缓存当前类实例引用,再定义load普通函数即可通过闭包访问,同样不影响Grid对回调this的绑定。
export class ToolSelectionComponent implements OnInit { @ViewChild('toolGroupGrid') public grid: GridComponent; public tools: Tool[] = [...]; public toolGroups: { Id: number, Name: string }[] = [...]; public toolsGroupAssignments: { GroupId: number, ToolId: bigint }[] = [...]; // 先声明类型,暂不赋值 public childGrid: GridModel | GridComponent; ngOnInit(): void { // 此处this为当前组件实例,缓存到局部变量 const componentRef = this; this.childGrid = { columns: [...], load() { const grid = this as GridComponent; const groupId = grid.parentDetails.parentRowData['Id']; grid.dataSource = componentRef.tools.filter(t => t.groupId === groupId); } } } ... }
原理说明
Grid组件内部调用传入的load回调时,是通过Function.prototype.call/apply方法显式将Grid自身实例绑定为普通函数的this,但箭头函数的this是词法作用域静态绑定的,无法被call/apply修改,这就是为什么用箭头函数定义load时拿不到Grid实例的原因。
上面两种方案都没有修改load的普通函数形式,Grid的this绑定逻辑完全不受影响,同时通过闭包提前缓存了外层类实例的引用,实现两个上下文的同时访问。
内容的提问来源于stack exchange,提问作者Marcel Lorenz
相关产品推荐
相关产品推荐

