TypeScript中d3.js回调里如何访问类实例的this上下文
问题描述
我在使用D3.js的API,其中on方法的回调定义如下:
on(typenames: "tick" | "end" | string): ((this: Simulation<NodeDatum, LinkDatum>) => void) | undefined;
我的简化代码如下:
class DiagramBuilder { private force: d3Force.Simulation<d3Force.SimulationNodeDatum, undefined>; private importantVariable: string = "need this"; registerStuff() { this.force = d3Force .forceSimulation(); this.force .on("tick", this.tick); } tick() { // 这里需要访问this.importantVariable,但当前this指向Simulation实例 } }
现在的问题是:回调里的this是Simulation<NodeDatum, LinkDatum>实例,但我需要访问DiagramBuilder类实例的importantVariable。
我已经知道三种解决方案:
- 使用
bind():比如this.force.on("tick", this.tick.bind(this)) - 创建
DiagramBuilder的静态单例实例 - 注册回调时用箭头函数传参:
同时修改this.force.on("tick", () => this.tick(this));tick方法:
但这种方式要求所有调用tick(builder: DiagramBuilder) { // 使用builder.importantVariable }tick的地方都必须传入DiagramBuilder实例,比较麻烦。
有没有比这些方案更简洁的实现方法?
更简洁的解决方案
方案1:直接在回调中使用箭头函数
注册回调时直接用箭头函数包裹逻辑,箭头函数会自动捕获当前上下文的this(即DiagramBuilder实例),同时还能通过参数拿到D3的Simulation相关事件对象:
registerStuff() { this.force = d3Force.forceSimulation(); this.force.on("tick", (event) => { // 此处this指向DiagramBuilder实例,可直接访问属性 console.log(this.importantVariable); // 如需获取Simulation实例,可通过event.source获取 console.log(event.source); }); }
方案2:将tick定义为类字段箭头函数
把tick直接定义为类的箭头函数字段,它的this会永久绑定到类实例,无需额外处理绑定逻辑:
class DiagramBuilder { private force: d3Force.Simulation<d3Force.SimulationNodeDatum, undefined>; private importantVariable: string = "need this"; // 箭头函数形式的类字段,this自动绑定到DiagramBuilder实例 private tick = () => { console.log(this.importantVariable); // 如需访问Simulation实例,直接通过this.force获取即可 console.log(this.force); }; registerStuff() { this.force = d3Force.forceSimulation(); this.force.on("tick", this.tick); } }
这两种方案都不需要额外的bind操作或传参,代码简洁直观。其中方案2还能把tick的逻辑单独抽离,保持代码结构清晰。
内容的提问来源于stack exchange,提问作者Alan Clark
相关产品推荐
相关产品推荐

