简体   繁体   English

如何将相同的事件处理程序用于click和touchend事件,但仅运行其中之一?

[英]How to use same event handler for click and touchend events but only run one of them?

Here is my code for overlay controls I'm working on https://repl.it/repls/AdoredMundaneFinance#index.js .这是我正在使用https://repl.it/repls/AdoredMundaneFinance#index.js的叠加控件的代码。 you can try interacting with it to see what functionality it offers.您可以尝试与之交互以查看其提供的功能。

I've come across an issue where on touch devices, event for touchend and click both are fired.我遇到了一个问题,即在触摸设备上触发touchend的事件和click都被触发了。 Now Ive googled a lot,现在我已经用谷歌搜索了很多,

a.一种。 I don't want to throttle due to user experience reasons.由于用户体验原因,我不想节制 Tried and didn't like it.尝试过,不喜欢它。

b. b。 Tried event.preventDefault() , it ensures only one event is used BUT it stops event from reaching the target children, ie child divs which are supposed to receive these clicks/taps, so can't use this.尝试过event.preventDefault() ,它确保仅使用一个事件,但会阻止事件到达目标子级,即应该接收这些点击/轻击的子级div,因此不能使用它。

c. C。 I tried event.stopPropogation() but that is causing other issues, I even tried calling it only when event is cancelable, you can try and see what I'm trying to say.我尝试了event.stopPropogation(),但这引起了其他问题,我什至尝试仅在事件可取消时才调用它,您可以尝试看看我要说的是什么。

d. d。 I'm now trying to detect if the device is touch and based on that assign functions, but again I don't want to extend my problem to touch detection as well, as there is no "true" detection method, I don't want to risk that.我现在正在尝试检测设备是否为触摸设备并基于该分配功能,但是我也不想将问题也扩展到触摸检测,因为没有“真正的”检测方法,我不会想要冒险。 What if someone is using mouse on touch device and click was being fired?如果有人在触摸设备上使用鼠标并且触发了点击该怎么办? etc etc.等等等

Please Help.请帮忙。

react:反应:

class App extends React.Component {
  constructor() {
    super();
    this.hideAfterXTimeout = null;
    this.state = {
      visible: false
    };
  }

  overlayRef(ref) {
    if (!this.overlay) {
      this.overlay = ref;
      this.overlay.addEventListener("click", this.clickTouchEffect.bind(this));
      this.overlay.addEventListener(
        "touchend",
        this.clickTouchEffect.bind(this)
      );
      let throttledHandler = this.throttle(300, this.mouseMoveEffect.bind(this));
            this.overlay.addEventListener(
        "mousemove",
        throttledHandler.bind(this)
      );
    }
  }

  mouseMoveEffect(event) {
    console.dir("called");
    this.showControls();
  }

  clickTouchEffect(event) {
    if (!event.target.hasAttribute("data-video")) {
      if (this.state.visible) {
        this.hideControls();
      } else {
        this.showControls();
      }
    } else {
      this.showControls();
    }
  }

  throttle(delay, fn) {
    let lastCall = 0;
    return function (...args) {
      const now = (new Date).getTime();
      if (now - lastCall < delay) {
        return;
      }
      lastCall = now;
      return fn(...args);
    }
  }

  showControls() {
    if(this.state.visible !== true){
      this.setState({
        visible: true
      });
    }
    if (this.hideAfterXTimeout) {
      clearTimeout(this.hideAfterXTimeout);
      this.hideAfterXTimeout = null;
    }
    let _me = this;
    this.hideAfterXTimeout = setTimeout(() => {
      _me.hideControls();
    }, 5000);
    this.overlay.classList.remove("hide");
  }

  hideControls() {
    this.setState({
      visible: false
    });
    if (this.hideAfterXTimeout) {
      clearTimeout(this.hideAfterXTimeout);
      this.hideAfterXTimeout = null;
    }
    this.overlay.classList.add("hide");
  }

  cc(){
    console.log("clicked");
  }

  render() {
    return (
      <div ref={this.overlayRef.bind(this)} className="overlay hide">
      <div className="visibility">
        <div onClick={this.cc.bind(this)} data-video="control" className="controls">
          CC
        </div>
      </div>
      </div>
    );
  }
}


ReactDOM.render(<App />, document.getElementById('app'));

css: CSS:

.App {
  font-family: sans-serif;
  text-align: center;
}

.overlay {
  width: 720px;
  height: 405px;
  outline: 1px solid red;

  opacity: 1;
  visibility: visible;
  transition: 0.3s ease-out opacity;
}

.overlay.hide {
  opacity: 0;
}

.overlay.hide > .visibility {
  visibility: hidden;
}

.overlay > .visibility {
  visibility: visible;
}

.controls {
  width: 64px;
  height: 64px;
  outline: 1px solid blue;

Here is my code for overlay controls I'm working on https://repl.it/repls/AdoredMundaneFinance#index.js .这是我正在使用https://repl.it/repls/AdoredMundaneFinance#index.js的叠加控件的代码。 you can try interacting with it to see what functionality it offers.您可以尝试与之交互以查看其提供的功能。

I've come across an issue where on touch devices, event for touchend and click both are fired.我遇到了一个问题,即在触摸设备上触发touchend的事件和click都被触发了。 Now Ive googled a lot,现在我已经用谷歌搜索了很多,

a.一种。 I don't want to throttle due to user experience reasons.由于用户体验原因,我不想节制 Tried and didn't like it.尝试过,不喜欢它。

b. b。 Tried event.preventDefault() , it ensures only one event is used BUT it stops event from reaching the target children, ie child divs which are supposed to receive these clicks/taps, so can't use this.尝试过event.preventDefault() ,它确保仅使用一个事件,但会阻止事件到达目标子级,即应该接收这些点击/轻击的子级div,因此不能使用它。

c. C。 I tried event.stopPropogation() but that is causing other issues, I even tried calling it only when event is cancelable, you can try and see what I'm trying to say.我尝试了event.stopPropogation(),但这引起了其他问题,我什至尝试仅在事件可取消时才调用它,您可以尝试看看我要说的是什么。

d. d。 I'm now trying to detect if the device is touch and based on that assign functions, but again I don't want to extend my problem to touch detection as well, as there is no "true" detection method, I don't want to risk that.我现在正在尝试检测设备是否为触摸设备并基于该分配功能,但是我也不想将问题也扩展到触摸检测,因为没有“真正的”检测方法,我不会想要冒险。 What if someone is using mouse on touch device and click was being fired?如果有人在触摸设备上使用鼠标并且触发了点击该怎么办? etc etc.等等等

Please Help.请帮忙。

react:反应:

class App extends React.Component {
  constructor() {
    super();
    this.hideAfterXTimeout = null;
    this.state = {
      visible: false
    };
  }

  overlayRef(ref) {
    if (!this.overlay) {
      this.overlay = ref;
      this.overlay.addEventListener("click", this.clickTouchEffect.bind(this));
      this.overlay.addEventListener(
        "touchend",
        this.clickTouchEffect.bind(this)
      );
      let throttledHandler = this.throttle(300, this.mouseMoveEffect.bind(this));
            this.overlay.addEventListener(
        "mousemove",
        throttledHandler.bind(this)
      );
    }
  }

  mouseMoveEffect(event) {
    console.dir("called");
    this.showControls();
  }

  clickTouchEffect(event) {
    if (!event.target.hasAttribute("data-video")) {
      if (this.state.visible) {
        this.hideControls();
      } else {
        this.showControls();
      }
    } else {
      this.showControls();
    }
  }

  throttle(delay, fn) {
    let lastCall = 0;
    return function (...args) {
      const now = (new Date).getTime();
      if (now - lastCall < delay) {
        return;
      }
      lastCall = now;
      return fn(...args);
    }
  }

  showControls() {
    if(this.state.visible !== true){
      this.setState({
        visible: true
      });
    }
    if (this.hideAfterXTimeout) {
      clearTimeout(this.hideAfterXTimeout);
      this.hideAfterXTimeout = null;
    }
    let _me = this;
    this.hideAfterXTimeout = setTimeout(() => {
      _me.hideControls();
    }, 5000);
    this.overlay.classList.remove("hide");
  }

  hideControls() {
    this.setState({
      visible: false
    });
    if (this.hideAfterXTimeout) {
      clearTimeout(this.hideAfterXTimeout);
      this.hideAfterXTimeout = null;
    }
    this.overlay.classList.add("hide");
  }

  cc(){
    console.log("clicked");
  }

  render() {
    return (
      <div ref={this.overlayRef.bind(this)} className="overlay hide">
      <div className="visibility">
        <div onClick={this.cc.bind(this)} data-video="control" className="controls">
          CC
        </div>
      </div>
      </div>
    );
  }
}


ReactDOM.render(<App />, document.getElementById('app'));

css: CSS:

.App {
  font-family: sans-serif;
  text-align: center;
}

.overlay {
  width: 720px;
  height: 405px;
  outline: 1px solid red;

  opacity: 1;
  visibility: visible;
  transition: 0.3s ease-out opacity;
}

.overlay.hide {
  opacity: 0;
}

.overlay.hide > .visibility {
  visibility: hidden;
}

.overlay > .visibility {
  visibility: visible;
}

.controls {
  width: 64px;
  height: 64px;
  outline: 1px solid blue;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 touchstart 和 touchend 事件跟踪移动设备上跨域 iframe 的点击 - How to use touchstart and touchend events to track click on a cross domain iframe on mobile devices JavaScript中同时存在两个事件,单击事件处理程序未执行 - two events at the same time in JavaScript, click event handler not executed 与“标准”功能和事件处理程序使用相同的功能 - Use same function as “standard” one and as an event handler 如何在没有在执行程序函数中添加事件处理程序的情况下将 Promise 与“click”事件一起使用? - How do I use Promises with ´click´ events without adding event handler in the executor function? 处理多个事件,但仅针对一个事件触发处理程序 - Handling multiple events but fire handler only for one event JS事件。 仅事件处理函数之一被调用? - JS events. Only one of the event handler function is being called? 如何在点击事件处理程序中使用ChartJS对象? - How to use ChartJS object in a click event handler? 是否有更优雅的方式来检测触摸事件支持并分配“点击”或“touchend”事件? - Is there a more elegant way to detect touch events support and assign either a “click” or “touchend” event? 2单击一个元素上的事件,只需要运行一个元素 - 2 click events on one element, only one needs to run 仅当事件以特定顺序发生时,才如何触发jquery事件处理程序? - How to trigger jquery event handler only if events happened in a specific order?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM