关于点透事件这里不再赘述,如果不清楚的可以上网搜一搜,或者看小火柴的这篇文章

这里是自己在做移动端时,在列表滑动的时候,遇到的点透问题。出现这个问题的来由是因为在转场的时候,各个手机的转场效果不一样,有的比较好,但是在有些低端机上,转场显得有点卡,于是就把过渡效果去掉了,因此就是直接的路由切换。【具体事件具体分析,可能我遇到的问题并不适合你,这里只是贴出来共享】

先看下面两张图片:



点击列表页的按钮会切换到下一个页面,但是在下一个页面上的每一个条目都是可以点击的,这时就会触发了下一个页面的弹窗,事实上我们并不想直接显示这个弹窗,而是要等待用户点击。

你可能在项目中的列表页写了如下的一段代码:

render() {
return (
<ul className="list">
{
list.map((l, index) => {
return (
<li key={ `list${index}` } onClick={ () => doSomething() }>
{ `item${index}` }
</li>
)
})
}
</ul>
);
}

在一个列表中的每个项目上绑定了点击事件,但是当点击之后切换到下一页。当时移动端的点击事件都会有300ms的延迟,因此在切换了页面之后,浏览器会再次判断点击的行为,此时如果下一个页面都有可以触发点击的元素,这时候就触发了下一个页面的点击行为。

于是,你可能会这么做,将onClick事件换成onTouchEnd事件

<li
key={ `list${index}` }
onTouchStart= { event => event.preventDefault() }
onTouchEnd={ () => doSomething() }>
{ `item${index}` }
</li>

但是,每次滑动的时候,其实你也触发了onTouchEnd事件,于是每次滑动你都会点击进入到下一页。于是你又想,加上一个onTouchStart事件,然后阻止掉默认事件,尼玛发现滑都滑不动了。

因此针对常用的几种解决点透事件的方法,我想了几种解决方案:

方案一:自己模拟Tap事件

大致的代码如下:

var list = document.querySelector('#list');
var dragState = {}; list.addEventListener('touchstart', function(event) {
var touch = event.touches[0];
dragState.startTime = new Date();
dragState.startLeft = touch.pageX;
dragState.startTop = touch.pageY;
dragState.startTopAbsolute = touch.clientY;
}); list.addEventListener('touchmove', function(event) {
var touch = event.touches[0];
dragState.currentLeft = touch.pageX;
dragState.currentTop = touch.pageY;
dragState.currentTopAbsolute = touch.clientY;
}); list.addEventListener('touchend', function() {
var dragDuration = new Date() - dragState.startTime;
var offsetLeft = dragState.currentLeft - dragState.startLeft;
var offsetTop = dragState.currentTop - dragState.startTop; if (dragDuration < 300) {
var fireTap = Math.abs(offsetLeft) < 10 && Math.abs(offsetTop < 10);
if (isNaN(offsetLeft) || isNaN(offsetTop)) {
fireTap = true;
}
if (fireTap) {
alert('tap');
}
}
dragState = {};
});

判断水平位移差和垂直位移差都小于10像素,并且touchstarttouchend的时间差小于300ms时,即认为触发了Tap事件。

方案二:加入转场动画

既然是因为转场动画在某些机型上比较卡的原因造成的,那么如果不是太考虑性能的话,可以加上转场动画,关于react中的转场动画,时间大概在300ms就好,可以看我之前对于转场代码的研究:react-css3-transition-group

方案三:在目标页面加入遮罩层

在目标页面加上一层透明的弹层,使上一个页面的点击在此弹层上失效,具体做法为使用一个高阶组件,在高阶组件中添加一个定时器,在每个页面加载的时候生成一个弹层,400ms之后消失弹层即可。

import React from 'react';

const styles = {
modal: {
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: 20,
backgroundColor: 'transparent'
}
}; const ComponentWrapper = MyComponent => { const ComponentTemplate = React.createClass({
getInitialState() {
return {
modal: true
};
}, componentDidMount() {
this.modalInter = setTimeout(() => {
this.setState({ modal: false });
}, 400);
}, componentWillUnmount() {
this.hideTips();
this.modalInter && clearTimeout(this.modalInter);
}, render() {
return (
<Page style={ this.props.style }>
<MyComponent { ...this.props } container={ this } />
{ this.state.modal && <div style={ styles.modal }></div> }
</Page>
)
}
}); return ComponentTemplate;
}; export default ComponentWrapper;

另外在0.13.3版本的react还支持mixins的时候,可以添加如下代码:

import React from 'react';
import ReactDOM from 'react-dom'; const styles = {
modal: {
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: 20,
backgroundColor: 'transparent'
}
}; const clickThroughMixin = {
getInitialState() {
return {
clickThroughModal: true
}
}, componentDidMount() {
this._renderModal();
this.modalInter = setTimeout(() => {
this._modalTarget && ReactDOM.unmountComponentAtNode(this._modalTarget);
this._modalTarget.remove();
}, 400);
}, componentWillUnmount() {
this.modalInter && clearTimeout(this.modalInter);
}, _renderModal() {
if (!this._modalTarget) {
this._modalTarget = document.createElement('div');
this._container = this._getContainerDOMNode().appendChild(this._modalTarget);
ReactDOM.unstable_renderSubtreeIntoContainer(
this, (<div style={ styles.modal }></div>), this._modalTarget
);
}
}, _getContainerDOMNode() {
const node = ReactDOM.findDOMNode(this), body = document.body;
return node ? node.parentNode || body : body;
}
}; export default clickThroughMixin;

移动端APP列表点透事件处理方法的更多相关文章

  1. 报表开发工具Finereport移动端app js接口列表【全】

    应用报表工具Finereport的开发人员会发现其移动端app 同样也推出了很多js接口,那这些接口到底有多少,其移动端又有哪些地方支持调用js,这些接口具体又该如何调用呢.根据我平时的开发经验,给大 ...

  2. 如何在移动端app中应用字体图标icon fonts (转)

    原文: http://www.cnblogs.com/willian/p/4166757.html?utm_source=tuicool&utm_medium=referral How to ...

  3. 如何在移动端app中应用字体图标icon fonts

    How to use icon fonts in your mobile apps 在任何APP设计中实现可图形的矢量缩放最完美的方式是使用字体图标. 移动端的设计变的越来越复杂.原因在于多样的屏幕尺 ...

  4. 移动端App uni-app + mui 开发记录

    前言 uni-app uni-app是DCloud推出的终极跨平台解决方案,是一个使用Vue.js开发所有前端应用的框架,官网:https://uniapp.dcloud.io/ mui 号称最接近原 ...

  5. 【Android端 APP GPU过度绘制】GPU过度绘制及优化

    一.Android端的卡顿 Android端APP在具体使用的过程中容易出现卡顿的情况,比如查看页面时出现一顿一顿的感受,切换tab之后响应很慢,或者具体滑动操作的时候也很慢. 二.卡顿的原因 卡顿的 ...

  6. 从下拉菜单拖拽一个元素 出来,插入到页面中的app 列表中

    1,实现功能:从下拉菜单拖拽一个元素 出来,插入到页面中的app 列表中 并实现app向后移动一个元素的位置: 2.实现思路: 01.遍历下拉菜单,添加拖拽方法,实现位置移动功能: 02.遍历app列 ...

  7. 【转】移动端App测试实用指南

    转自:互联网那点事 英文原文: http://mobile.smashingmagazine.com/2012/10/22/a-guide-to-mobile-app-testing/ 测试人员常被看 ...

  8. 【转】【CDC翻客】移动端App测试实用指南

     译者注:本文从测试人员的角度出发,提出了100多个在测试移动App过程中需要考虑的问题.不管你是测试人员.开发.产品经理或是交互设计师,在进行移动App开发时,这些问题都很有参考价值.我和Queen ...

  9. Android学习系列(15)--App列表之游标ListView(索引ListView)

    游标ListView,提供索引标签,使用户能够快速定位列表项.      也可以叫索引ListView,有的人称也为Tweaked ListView,可能更形象些吧.      一看图啥都懂了: 1. ...

随机推荐

  1. 利用GDAL进行工具开源化改造

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 为利于项目实施,团队用AE写过一个插件式的工具集,主要包括了数 ...

  2. ES6之Promise

    Promise是一个对象,用来传递异步操作的消息,他有两个特点:第一对象的状态不受外界的影响,第二一旦状态改变就不会在变,任何时候都可以得到这个结果,他有两个参数分别是resolve(他的作用是将Pr ...

  3. 502 VS 504

    本文同时发表在https://github.com/zhangyachen/zhangyachen.github.io/issues/89 首先看一下概念: 502:作为网关或者代理工作的服务器尝试执 ...

  4. nova创建虚拟机源码分析系列之三 PasteDeploy

    上一篇博文介绍WSGI在nova创建虚拟机过程的作用是解析URL,是以一个最简单的例子去给读者有一个印象.在openstack中URL复杂程度也大大超过上一个例子.所以openstack使用了Past ...

  5. Java基础--二进制运算

    1. System.out.println((byte)0x8f); 结果是? 2.System.out.println((byte)(0xc5>>1)); 结果是? 3.System.o ...

  6. Java 向下转型

    1.Java 中父类直接向子类转型的不合法的,可以编译但运行时报错. Java中子类直接向父类转型 是合法的,但转型后,可以执行的方法仅限存在于父类中的,在执行时,先看子类的是否有定义,有就执行,没有 ...

  7. Ajax异步提交登录(2)--登录使用

    http://cjp1989.iteye.com/blog/1740964 1.Ajax的原理: Ajax的原理就是:通过javascript的方式,将前台数据通过xmlhttp对象传递到后台,后台在 ...

  8. Vuex- Action的 { commit }

    Vuex 中 使用 Action 处理异步请求时,常规写法如下: getMenuAction:(context) =>{ context.commit('SET_MENU_LIST',['承保2 ...

  9. thinkinginjava学习笔记10_容器

    Java中并没有像Perl.Python.Ruby那样对容器有直接的支持,但是可以依靠容器类来完成相同的工作: 泛型 使用一个ArrayList对象可以保存一系列的对象,如: ArrayList ap ...

  10. Android中Handler的消息处理机制以及源码分析

    在实际项目当中,一个很常见的需求场景就是在根据子线程当中的数据去更新ui.我们知道,android中ui是单线程模型的,就是只能在UI线程(也称为主线程)中更新ui.而一些耗时操作,比如数据库,网络请 ...