Могу ли я быстро щелкнуть ReactJS, работающий в Cordova

#cordova #reactjs #fastclick.js

#кордова #reactjs #fastclick.js

Вопрос:

Работает ли fastclick с системой событий ReactJS? Похоже, это не происходит при запуске через Cordova на iOS или Android. Если нет, есть ли другой способ получить те же результаты. В моем приложении нет функции двойного нажатия, поэтому я бы хотел, если возможно, устранить эту задержку по всем направлениям…

Ответ №1:

Редактировать

Facebook решил не добавлять поддержку для определения пользовательских типов событий и рекомендует вам использовать что-то вроде react-tappable, чтобы вы могли написать что-то вроде <Tappable onTap={}> .


Facebook работает над решением в форме TapEventPlugin , но оно не будет доступно , пока они не примут некоторые решения.


Если вы читаете это, вы, вероятно, работаете над проектом, который не может дождаться, пока они не выяснят, как они хотят его опубликовать.

Это репозиторий для вас: 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. К ВАШЕМУ сведению, onTouchTap работает как щелчок (для не сенсорного экрана).

2. Итак, чтобы было ясно, должен ли я использовать react-tap-event-plugin или React-Tappable сейчас?

3. Оба работают, но react-tappable кажется более разумным выбором. Нет исправления обезьяны.

4. Спасибо, вероятно, так и будет, поскольку react-tap-event-plugin, похоже, не работает с react@15.3.2

5. Требуется ли это решение только для мобильных браузеров?

Ответ №2:

Я получил FastClick для работы с React в проекте Webpack. Несколько вещей кажутся сложными, но в основном это работает. (Обновление: только переключатель, который имитировал щелчки по скрытому флажку, был сложным — это было бы проблемой независимо от React). Вот как я его включил:

npm install -S fastclick

В main.jsx :

 import FastClick from 'fastclick';

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

Поэтому, даже если вы не используете Webpack или Browserify, я предполагаю, что пока вы можете запускать прослушиватель событий загрузки, все будет в порядке.

Комментарии:

1. Для меня это сработало идеально. Черт возьми, в моем изоморфном приложении react, созданном с помощью webpack, мне пришлось отключить модуль fastclick при сборке сервера с помощью new webpack.NormalModuleReplacementPlugin(/fastclick$/i, 'node-noop')

2. @Federico круто, было бы полезно узнать, нужно ли мне идти изоморфно!

3. Су… Я только что узнал, что, к сожалению, это решение не подходит для использования обработчиков onClick React. Это работает только для ваших общих элементов HTML — привязок, кнопок и т. Д. Вот лучшее, что я нашел: github.com/zilverline/react-tap-event-plugin

4. Какое поведение вы видите? У меня не было никаких проблем с onClick обработчиками.

5. Вы создаете компонент React с onClick помощью prop, но не передаете его компоненту, что бы он ни render() возвращал, так что в конечном итоге он попадает в реальный HTML-компонент? Насколько я знаю, onClick обработчик компонента React ничего не сделает, вы должны передать его элементу HTML.

Ответ №3:

Недавно мы создали компонент React, похожий на fastclick, за исключением того, что он намного проще и требует обратного вызова вручную. Он довольно короткий, поэтому я опубликую его здесь:

 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' amp;amp; this.props.handler.apply(this, arguments)
  },

  getCoords: function(e) {
    if ( e.touches amp;amp; 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 amp;amp; classNames.push(this.props.className)
    this.state.touchdown amp;amp; 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 prop в качестве обратного вызова и оберните свой контент внутри. Это также работает для систем, в которых есть события касания и нажатия (например, новые ноутбуки с Windows 8). Пример:

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

Комментарии:

1. Я имею в виду, это не решение типа «бам-бам, спасибо, мама», которое мгновенно избавляет от раздражающей задержки щелчка для всего на странице, не так ли? В этом смысл Fastclick

Ответ №4:

У меня были проблемы с использованием метода Дэвида, поэтому в качестве альтернативы FastClick я реализовал mixin с использованием HammerJS для события. Немного больше кода для настройки события, но работает нормально.

 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"/>                
                   );
          }
      });
 

Ответ №5:

Казалось, что в моем приложении Cordova все работает нормально, но есть одна серьезная проблема, с которой я столкнулся.

Когда элемент щелкается с помощью React FastClick, а следующее отображаемое представление содержит интерактивный элемент в той же позиции, событие onTouchEnd также регистрируется во втором элементе.

Я отказался от FastClick, так как не хочу выравнивать свои кнопки, чтобы избежать нежелательного поведения, но мне нужно что-то, чтобы заменить его, поскольку задержка щелчка кажется довольно плохой.

Комментарии:

1. У меня были похожие проблемы, когда кнопка нажималась немедленно, но затем в некоторых средах (браузерах Android) снова нажималась через 300 мс. Плагин события касания, используемый в библиотеках react touch , добавляет приятный обратный вызов onTouchTap, но он не работает на бесконтактных вводах. Создание плагина для реагирования на события может быть правильным решением. Я до сих пор не нашел ответа…

2. Спасибо за информацию, на самом деле после отказа от FastClick я все еще сталкиваюсь с аналогичными проблемами «регистры нажатия два раза», хотя и в разных частях приложения, чем раньше. Пока тоже не нашел решения…

3. @PirkkaEsko итак, FastClick не был причиной onTouchEnd проблемы, которую вы видели?

4. Честно говоря, я больше не помню деталей, но мой комментарий выше предполагает, что FastClick не был основной причиной, но мог иметь к ним какое-то отношение, поскольку поведение было изменено (проблемы возникали в разных частях приложения после удаления FastClick).

5. Я обнаружил такое поведение как с помощью fastclick, так и с помощью плагина react-tap-event. До сих пор не нашел хорошего решения.

Ответ №6:

Вы также можете использовать react-fastclick (https://github.com/JakeSidSmith/react-fastclick ) из нпм:

 npm i react-fastclick --save
 

Используя его, вам не нужно изменять какой-либо свой код, и он работает действительно хорошо! Вам нужно потребовать это только один раз.

 require('react-fastclick');