fastclick是否与 ReactJS 的事件系统配合使用?当通过 Cordova 运行到 iOS 或 Android 时,它似乎并不适用。如果没有,是否有另一种方法可以获得相同的结果。我的应用程序没有双击功能,所以如果可能的话,我想全面消除这种延迟......
我可以在 Cordova 中运行 Fastclick ReactJS
编辑
Facebook 决定不添加对定义自定义事件类型的支持,并建议您使用react-tappable 之类的东西,以便您可以编写类似<Tappable onTap={}>
.
Facebook 正在以 的形式研究解决方案TapEventPlugin
,但在他们做出某些决定之前不会提供 。
如果您正在阅读本文,那么您可能正在从事一个项目,该项目迫不及待地想知道如何发布它。
这个 repo 是给你的:https : //github.com/zilverline/react-tap-event-plugin
当 Facebook 解决#436和#1170 时,这个 repo 将消失。
此解决方案适用于 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
不再需要)。
我让 FastClick 在一个 Webpack 项目中与 React 一起工作。一些事情看起来很挑剔,但大部分都有效。(更新:只有一个模拟点击隐藏复选框的切换开关是挑剔的——不管react如何,这都是一个问题)。这是我打开它的方法:
npm install -S fastclick
在main.jsx
:
import FastClick from 'fastclick';
window.addEventListener('load', () => {
FastClick.attach(document.body);
});
因此,即使您不使用 Webpack 或 Browserify,我猜只要您可以运行加载事件侦听器,就可以了。
我们最近创建了一个类似于 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 为事件实现了一个 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"/>
);
}
});
它在我的 Cordova 应用程序中似乎运行良好,但我遇到了一个重大问题。
当使用 React+FastClick 单击一个元素,并且下一个渲染视图在同一位置包含一个可单击元素时,也会在第二个元素中注册一个 onTouchEnd 事件。
我放弃了 FastClick,因为我不想对齐我的按钮以避免不必要的行为,但我需要一些东西来替换它,因为点击延迟感觉很糟糕。