【问题标题】:Question re: TypeScript object property pointers passed into methods问题重新:TypeScript 对象属性指针传递给方法
【发布时间】:2020-09-15 20:41:54
【问题描述】:

我是 TypeScript 的新手,正在尝试使用 D3.js 创建一个带有两个句柄的简单范围滑块。

我为滑块对象创建了一个基本类:

export class VerticalRangeSlider{
    private sliderContainer:  d3.Selection<SVGGElement, any, HTMLDivElement, any>;
    private scale: d3.ScaleLinear<number, number>;
    
    private sliderTopBound: number;
    private sliderBottomBound: number;

    private handleTopY: number;
    private handleBottomY: number;
    private handleTop: d3.Selection<SVGCircleElement, any, HTMLDivElement, any>;
    private handleBottom: d3.Selection<SVGCircleElement, any, HTMLDivElement, any>;

constructor(slContainer: d3.Selection<SVGGElement, any, HTMLDivElement, any>, scl: d3.ScaleLinear<number, number>){
    this.sliderContainer = slContainer;
    this.scale = scl;

    this.sliderTopBound = 0;
    this.sliderBottomBound = scl.range()[0];
    this.handleTopY = this.sliderTopBound;
    this.handleBottomY = this.sliderBottomBound;

    this.initSlider();
}

这两个句柄是在 initSlider 方法中创建的。我有一个匿名函数被调用来处理拖动事件,它调用 moveHandle 方法来重新渲染圆圈。

因为我发现 this. 在匿名函数中有不同的上下文,所以我在 initSlider 中声明了一个变量来保存指向父对象的指针:var parentObject = this;

   this.handleTop = this.sliderContainer.insert("circle", ".track-overlay")
    .attr("class", "handle")
    .attr("r", 9)
    .attr("cy", this.handleTopY)
    .attr("desc", this.handleTopY)
    .call(d3.drag()
    .on('drag', function(){
       parentObject.moveHandle(parentObject.handleTop, parentObject.handleTopY, d3.event.dy, parentObject.sliderTopBound, parentObject.handleBottomY);
    }));

    this.handleBottom = this.sliderContainer.insert("circle", ".track-overlay")
    .attr("class", "handle")
    .attr("r", 9)
    .attr("cy", this.handleBottomY)
    .attr("desc", this.handleBottomY)
    .call(d3.drag()
    .on('drag', function(){
       parentObject.moveHandle(parentObject.handleBottom, parentObject.handleBottomY, d3.event.dy, parentObject.handleTopY, parentObject.sliderBottomBound);
    }));

我遇到了 moveHandle 方法的问题:

private moveHandle(handle: d3.Selection<SVGCircleElement, any, HTMLDivElement, any>, currentPosition: number, increment: number, topBound: number, bottomBound:number): void {
    
        var legalIncrement: number;
        //upward movement
        if(Math.sign(increment) === -1){
            legalIncrement = increment <= (currentPosition - topBound) ? increment : (currentPosition - topBound);
            console.log("allowed increment: "+legalIncrement);
        }
        //downward movement
        else {
            legalIncrement = increment <= (bottomBound - currentPosition) ? increment : (bottomBound - currentPosition);
            console.log("allowed increment: "+legalIncrement);

        }
        
    if(legalIncrement !== 0){
        currentPosition = (currentPosition + legalIncrement)
        handle.attr("transform", "translate(0," + currentPosition + ")");
    }

}

当我尝试拖动圆圈时,它们会按预期短暂呈现,但随后会立即恢复到原来的位置。

但是,当我将指向父对象的指针直接传递给 moveHandle 时,一切正常:parentObject: VerticalRangeSlider): void {

parentObject.handleBottomY = parentObject.handleBottomY + increment; parentObject.handleBottom.attr("cy", parentObject.handleBottomY);

我最初的假设是我将指向父对象属性的指针传递到我的方法中,但看起来情况并非如此。我最好的理论是正在创建新对象。

我非常感谢对此行为的任何见解(以及任何反馈以更好地构建我的 JS/TS 代码)。

谢谢!

【问题讨论】:

    标签: javascript typescript d3.js


    【解决方案1】:

    在您的代码中,您最终需要对父级的引用。要解决此问题,您可以使用arrow functions。使用function () {} 表单定义的函数将创建自己的this,因此需要像使用parentObject 一样保持对父this 的引用

    另一方面,箭头函数(=&gt; 形式)不绑定自己的 this。这意味着箭头函数中的this指的是父this,你不需要引用:你可以直接使用this

    我们也可以将drag 处理程序更改为箭头函数。

    这是您的代码,其中有一些更改。这可能不完全正确,因为我可能遗漏了一些意思:让我知道。

    this.handleTop = this.sliderContainer.insert("circle", ".track-overlay")
      .attr("class", "handle")
      .attr("r", 9)
      .attr("cy", this.handleTopY)
      .attr("desc", this.handleTopY)
      .call(d3.drag()
      .on('drag', () =>
         this.moveHandle(this.handleTop, this.handleTopY, d3.event.dy, this.sliderTopBound, this.handleBottomY);
      );
    
    this.handleBottom = this.sliderContainer.insert("circle", ".track-overlay")
    .attr("class", "handle")
    .attr("r", 9)
    .attr("cy", this.handleBottomY)
    .attr("desc", this.handleBottomY)
    .call(d3.drag()
    .on('drag', () => this.moveHandle(this.handleBottomY, this.handleTopY, d3.event.y, this.sliderBottomBound);
    );
    
    private moveHandle = (currentPosition: number, topBound: number, increment:number, bottomBound:number): void => {
            var legalIncrement: number;
            //upward movement
            if(Math.sign(increment) === -1){
                legalIncrement = increment <= (currentPosition - topBound) ? increment : (currentPosition - topBound);
                console.log("allowed increment: "+legalIncrement);
            }
            //downward movement
            else {
                legalIncrement = increment <= (bottomBound - currentPosition) ? increment : (bottomBound - currentPosition);
                console.log("allowed increment: "+legalIncrement);
    
            }
            
        if(legalIncrement !== 0){
            currentPosition = (currentPosition + legalIncrement)
            this.attr("transform", "translate(0," + currentPosition + ")");
        }
    
    }
    

    【讨论】:

    • 感谢您对“this”和箭头函数范围的洞察!这绝对有效。
    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 2017-06-21
    • 1970-01-01
    • 2012-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-30
    相关资源
    最近更新 更多