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";
}
}
几点注意事项
- 我更喜欢将 class 的东西放在 class 里面,没有额外的
var
在外面。
- 我也接受 ES5 和 ES6。
- 我读到我可以做到
window.mousemove.bind(() => { // Code });
,但我无法做到这一点。
您无法在 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。
- 我展示了两个可调整大小的元素。
一切正常,除了我不知道如何取消绑定 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";
}
}
几点注意事项
- 我更喜欢将 class 的东西放在 class 里面,没有额外的
var
在外面。 - 我也接受 ES5 和 ES6。
- 我读到我可以做到
window.mousemove.bind(() => { // Code });
,但我无法做到这一点。
您无法在 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。
- 我展示了两个可调整大小的元素。