我可以快速点击在Cordova中运行的ReactJS

时间:2014-06-20 21:20:12

标签: cordova reactjs fastclick.js

fastclick是否适用于ReactJS的事件系统?当通过Cordova运行到iOS或Android时,似乎没有采取任何措施。如果没有,是否有另一种获得相同结果的方法。我的应用没有双击功能,所以如果可能的话,我想全面消除这种延迟...

6 个答案:

答案 0 :(得分:28)

修改

Facebook决定not add support for defining custom event types并建议您使用类似react-tappable 的内容,以便您可以撰写<Tappable onTap={}>之类的内容。

Facebook以TapEventPlugin的形式开发解决方案,但won't be made available until they make some decisions

如果您正在阅读本文,那么您可能正在开展一个项目,该项目不能等到他们想知道如何发布它。

这个回购是给你的:https://github.com/zilverline/react-tap-event-plugin

当Facebook解决#436#1170时,此回购将会消失。

此解决方案适用于React 0.14.x和15.x。

npm i -S react-tap-event-plugin

使用示例:

var React = require("react");
var ReactDOM = require("react-dom");
injectTapEventPlugin = require("react-tap-event-plugin");
injectTapEventPlugin();

var Main = React.createClass({
  render: function() {
    return (
      <a
        href="#"
        onTouchTap={this.handleTouchTap}
        onClick={this.handleClick}>
        Tap Me
      </a>
    );
  },

  handleClick: function(e) {
    console.log("click", e);
  },

  handleTouchTap: function(e) {
    console.log("touchTap", e);
  }
});

ReactDOM.render(<Main />, document.getElementById("container"));

请注意,使用注射器时,您可能只需要使用onTouchTap(而不再使用onClick)。

答案 1 :(得分:17)

我在一个Webpack项目中使用FastClick与React一起工作。有些事情看起来很挑剔,但它主要起作用。 (更新:只有模拟隐藏复选框点击的切换开关很挑剔 - 无论React如何都会出现问题)。这是我打开它的方式:

npm install -S fastclick

main.jsx

import FastClick from 'fastclick';

window.addEventListener('load', () => {
  FastClick.attach(document.body);
});

所以,即使你没有使用Webpack或Browserify,我猜也只要你能运行加载事件监听器,你就可以了。

答案 2 :(得分:5)

我们最近创建了一个类似于fastclick的React组件,除了它更简单并需要手动回调。它很短,所以我会在这里发布:

React.initializeTouchEvents(true)

var TouchClick = React.createClass({

  defaults: {
    touched: false,
    touchdown: false,
    coords: { x:0, y:0 },
    evObj: {}
  },

  getInitialState: function() {
    return this.defaults
  },

  handler: function() {
    typeof this.props.handler == 'function' && this.props.handler.apply(this, arguments)
  },

  getCoords: function(e) {
    if ( e.touches && e.touches.length ) {
      var touch = e.touches[0]
      return {
        x: touch.pageX,
        y: touch.pageY
      }
    }
  },

  onTouchStart: function(e) {
    this.setState({ 
      touched: true, 
      touchdown: true,
      coords: this.getCoords(e),
      evObj: e
    })
  },

  onTouchMove: function(e) {
    var coords = this.getCoords(e)
    var distance = Math.max( 
      Math.abs(this.state.coords.x - coords.x), 
      Math.abs(this.state.coords.y - coords.y) 
    )
    if ( distance > 6 )
      this.setState({ touchdown: false })
  },

  onTouchEnd: function() {
    if(this.state.touchdown)
      this.handler.call(this, this.state.evObj)
    setTimeout(function() {
      if ( this.isMounted() )
        this.setState(this.defaults)
    }.bind(this), 4)
  },

  onClick: function() {
    if ( this.state.touched )
      return false
    this.setState(this.defaults)
    this.handler.apply(this, arguments)
  },

  render: function() {
    var classNames = ['touchclick']

    this.props.className && classNames.push(this.props.className)
    this.state.touchdown && classNames.push('touchdown')

    return React.DOM[this.props.nodeName || 'button']({
      className: classNames.join(' '),
      onTouchStart: this.onTouchStart,
      onTouchMove: this.onTouchMove,
      onTouchEnd: this.onTouchEnd,
      onClick: this.onClick
    }, this.props.children)
  }
})

只需将handler道具作为回调传递并将内容包装在内。这也适用于同时具有触摸和点击事件的系统(如较新的Windows 8笔记本电脑)。例如:

 <TouchClick handler={this.clickHandler} className='app'>
   <h1>Hello world</h1>
 </TouchClick>

答案 3 :(得分:3)

我在使用David的方法时遇到了问题,因此作为FastClick的替代方案,我使用HammerJs为该事件实现了一个mixin。 设置事件的代码多一点,但工作正常。

var HammerClickMixin = React.createClass({
    componentWillMount: function() {
        this.listeneres = [];

    },
    addTapEvent: function(element,callback) {
        var mc = new Hammer.Manager(element);
        mc.add(new Hammer.Tap({ event: 'doubletap', taps: 2 }));
        mc.add(new Hammer.Tap({ event: 'tap', taps: 1 }));
        mc.on('tap',callback);
        this.listeneres.push(mc);
    },
    addDoubleTap : function(element,callback){
        var mc = new Hammer.Manager(element);
        mc.add(new Hammer.Tap({ event: 'doubletap', taps: 2 }));
        mc.on('doubletap',callback);
        this.listeneres.push(mc);
    },
    componentWillUnmount: function() {
        for(var i= 0; i < this.listeneres.length; i++){
            this.listeneres[i].destroy();
        }
    }
});

然后可以按照以下方式使用:

 var Component = React.createClass({
          mixins: [HammerClickMixin],
          componentDidMount: function () {

              this.addTapEvent(this.refs.elementToClick.getDOMNode(),function(){
                  //Handle fast hammer tap!

              });
          },
          render: function () {
               return (
                        <div ref="elementToClick"/>                
                   );
          }
      });

答案 4 :(得分:2)

我的Cordova应用程序似乎工作正常,但我遇到了一个重大问题。

使用React + FastClick单击元素,并且下一个渲染视图包含位于相同位置的可单击元素时,onTouchEnd事件也会在第二个元素中注册。

我放弃了FastClick,因为我不想对齐我的按钮以避免不必要的行为,但我需要更换它,因为点击延迟感觉非常糟糕。

答案 5 :(得分:2)

您也可以使用npm:{/ p>中的react-fastclickhttps://github.com/JakeSidSmith/react-fastclick

npm i react-fastclick --save

使用它,您不必更改任何代码,它的工作非常好!你只需要一次。

require('react-fastclick');