fastclick はReactJSのイベントシステムで動作しますか? Cordovaを介してiOSまたはAndroidに実行する場合、実行されていないようです。そうでない場合、同じ結果を得る別の方法があります。私のアプリにはダブルタップ機能がないため、可能であれば、ボード全体でその遅延を削除したいです...
WebpackプロジェクトでFastClickをReactと連携させました。いくつかのことは細心の注意を払っているように見えますが、ほとんどは機能します。 (更新:非表示のチェックボックスのクリックをシミュレートするトグルスイッチのみが扱いにくい-これはReactに関係なく問題になる)。私がそれをオンにした方法は次のとおりです。
npm install -S fastclick
main.jsx
:
import FastClick from 'fastclick';
window.addEventListener('load', () => {
FastClick.attach(document.body);
});
したがって、WebpackまたはBrowserifyを使用していない場合でも、loadイベントリスナーを実行できる限り問題はないと思います。
最近、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
propをコールバックとして渡し、コンテンツを内部にラップするだけです。これは、タッチイベントとクリックイベントの両方があるシステムでも機能します(新しいWindows 8ラップトップなど)。例:
<TouchClick handler={this.clickHandler} className='app'>
<h1>Hello world</h1>
</TouchClick>
Davidのメソッドの使用に問題があったので、FastClickの代替として、イベントに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"/>
);
}
});
Cordovaアプリではうまく機能しているように見えましたが、私が遭遇した重大な問題が1つあります。
React + FastClickを使用して要素がクリックされ、次に表示されるビューに同じ位置にクリック可能な要素が含まれる場合、onTouchEndイベントも2番目の要素に登録されます。
不要な動作を避けるためにボタンを整列させたくないのでFastClickを捨てましたが、クリックの遅延がかなり悪く感じられるので、それを置き換えるものが必要です。
Npmからreact-fastclick
( https://github.com/JakeSidSmith/react-fastclick )を使用することもできます。
npm i react-fastclick --save
それを使用すると、コードを変更する必要がなく、本当に機能します!必要なのは一度だけです。
require('react-fastclick');