Class 事件绑定和解除绑定

Class events bind and unbind

一切正常,除了我不知道如何取消绑定 stop() 中的事件。

代码已更新

class Resizable {
  go(drag_el, resize_el) {
    this.resize_el = resize_el;

    drag_el.addEventListener("mousedown", () => {
      window.addEventListener("mousemove", this.resize.bind(this));
      window.addEventListener("mouseup", () => {
        window.removeEventListener("mousemove", this.resize.bind(this));
        window.removeEventListener("mouseup", this.resize.bind(this));
      });
    });
  }

  resize(e) {
    this.resize_el.style.width = e.clientX - this.resize_el.offsetLeft + "px";
  }
}

几点注意事项

您无法在 stop 函数中删除侦听器,因为您不知道它们的引用。

Mousemove事件不调用resize函数,它调用匿名函数

e => {
  this.resize(resize_el, e);
}

你可以将匿名函数的地址保存在变量中,并用它来移除监听器,就像这样

class Resizable {
  constructor() {
    this.mouseMoveHandler = (e) => {
      this.resize(resize_el, e);
    };

    this.mouseDownHandler = () => {
      window.addEventListener("mousemove", this.mouseMoveHandler);
    }

    this.mouseUpHandler = () => {
      window.removeEventListener("mousemove", this.mouseMoveHandler);
    }
  }

  go(drag_el, resize_el) {
    drag_el.addEventListener("mousedown", this.mouseDownHandler);

    window.addEventListener("mouseup", this.mouseUpHandler);
  }

  resize(resize_el, e) {
    resize_el.style.width = e.clientX - resize_el.offsetLeft + "px";
  }

  stop() {
    window.removeEventListener("mousemove", this.mouseMoveHandler); // ?
    // most likely you would like remove listeners from this.go
  }
}

您可以在 this article on Medium [removeEventListener() and anonymous function]

中找到更多信息

UPD(问题更新后):

.bind() 每次都创建新函数,因此您仍然无法删除事件侦听器。

在这里查看我的fiddle:https://jsfiddle.net/nvfcq80z/5/

不知怎的,saveli 说的是真的,你必须在删除监听器时调用相同的函数引用(指向监听器内部调用的相同函数),如果你想要更多解释,请确保你可以问

class Resizable {
   go(drag_el, resize_el) {
      this.resize_el=resize_el;
      drag_el.addEventListener("mousedown", () => {
         $(window).bind("mousemove", this.resize);
         $(window).bind("mouseup", this.stop);
      });
   }

   resize= (e) =>{
         this.resize_el.style.width = e.clientX - this.resize_el.offsetLeft + "px";;
    }
   stop =(event) =>{
                $(window).unbind(event,this.stop);
                $(window).unbind("mousemove",this.resize); 
    }

}

只用js编辑这个没有jquery

class Resizable {
   go(drag_el, resize_el) {
      this.resize_el=resize_el;
      drag_el.addEventListener("mousedown", () => {
         window.addEventListener("mousemove", this.resize);
         window.addEventListener("mouseup", this.stop);
      });
   }

   resize= (e) =>{
         this.resize_el.style.width = e.clientX - this.resize_el.offsetLeft + "px";
   }
  stop =(event) =>{ 
      window.removeEventListener(event,this.stop);
      window.removeEventListener("mousemove",this.resize);
   }

}

对于这种情况,我通常更喜欢直接将对象作为侦听器传递给 addEventListener:它使一切变得更容易 IMVHO。您只需实施 handleEvent 方法:

class Resizable {
  // Keeping a reference to the elements it's easier for the events handling
  constructor(drag_el, resize_el) {
    this.drag_el = drag_el;
    this.resize_el = resize_el;
    // The entry point event handler is added in the constructor
    // to avoid to add multiple listeners (e.g. in the original
    // code we could have called `go` method multiple times).
    this.drag_el.addEventListener("mousedown", () => {
      // Here we add the object itself as event handler
      window.addEventListener("mousemove", this);
      window.addEventListener("mouseup", this);
    });
  }

  resize(e) {
    this.resize_el.style.width = e.clientX - this.resize_el.offsetLeft + "px";
  }

  // Here we're removing the object itself as event handler
  stop() {
    window.removeEventListener("mousemove", this, false);
    window.removeEventListener("mouseup", this, false);
  }

  // Here we're handling the events: since we added the object
  // itself, `this` is still pointing to our instance of `Resizable`
  // so we can call its methods.
  handleEvent(event) {
    switch (event.type) {
        case "mousemove": 
          this.resize(event);
          break;
        case "mouseup":
          this.stop();
          break;
    }
  }
}

这种方法大大减少了绑定和箭头函数的使用。

在这里您可以找到 codepen demo 代码 运行。

我已经接受了我最喜欢的工作答案。但是我认为@SaveliTomac 和@ZER0 的组合将是最好的答案。

因此,我从两个世界中挑选了最好的,至少在我看来是这样。

https://jsfiddle.net/nhLjozm7/

HTML

<aside class="sidebar1">
  <div class="sidebar1-resize"></div>
</aside>

<div class="sidebar2">
  <div class="sidebar2-resize"></div>
</div>

JS

class Resizable {
  constructor(drag_el, resize_el) {
    this.drag_el = drag_el;
    this.resize_el = resize_el;

    this.handlers();
    this.events();
  }

  handlers() {
    this.mouseMoveHandler = (e) => {
      this.resize(this.resize_el, e);
    };

    this.mouseDownHandler = () => {
      window.addEventListener("mousemove", this.mouseMoveHandler);
    }

    this.mouseUpHandler = () => {
      window.removeEventListener("mousemove", this.mouseMoveHandler);
    }
  }

  events() {
    this.drag_el.addEventListener("mousedown", this.mouseDownHandler);
    window.addEventListener("mouseup", this.mouseUpHandler);
  }

  resize(resize_el, e) {
    resize_el.style.width = e.clientX - resize_el.offsetLeft + "px";
  }
}

let drag1 = document.querySelector(".sidebar1-resize");
let element1 = document.querySelector(".sidebar1");
new Resizable(drag1, element1);

let drag2 = document.querySelector(".sidebar2-resize");
let element2 = document.querySelector(".sidebar2");
new Resizable(drag2, element2);
  • 我喜欢@SaveliTomac 的更扁平的处理程序结构(没有事件嵌套)。
  • 我喜欢@ZER0 将调整大小手柄放在旁边而不是外面的方式。
  • 我喜欢@ZER0 和@SaveliTomac 解决方案如何支持多个可调整大小的区域。
  • 我喜欢@SaveliTomac 的简洁易读代码。
  • 我喜欢@ZER0 将值集直接放入构造函数中。
  • 我将所有处理程序包装到一个方法中。
  • 我将事件包装到一个方法中。
  • 我稍微更改了 HTML。
  • 我展示了两个可调整大小的元素。