JS案例 - 基于vue的移动端长按手势

================================惯例碎碎念前言================================

当时首先想到要做长按事件的时候,我想到的是vue内部的自定义指令,毕竟官网里边有这么一句描述:

有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令

但是项目用在app中,因为另一个未知原因的bug,自定义事件躺枪(至今死不瞑目)。长按事件被我改成了在初始化时,就直接绑定到需要他的dom上。

================================正经文================================

绑定的命令写在mounted钩子里,这是因为在created内部我也找不到dom,而在mounted阶段,所有的dom结构和数据都被展示到页面当中,

详情可以参见“vue生命周期强刷”:https://www.cnblogs.com/padding1015/p/9159381.html

所以,下边的代码经过不断的轮回,最终是写在mounted里边的

let oDiv = document.getElementById(‘canvas‘);

// 因为长按事件要加在div#canvas上的,如果事件是任何地方的话,就是document

1 oDiv.addEventListener("touchstart", function(e) {}, false);
2
3 oDiv.addEventListener("touchmove", function(e) {}, false);
4
5 oDiv.addEventListener("touchend", function(e) {}, false);

至于,三个绑定事件的回调里再写什么,就不太关vue的事了(dui,就是这么草率)。

在公布最终的成型代码之前,容我先补一波关于事件的”兵”。

主要兵线呢有三条:

中路:dom2级事件处理程序

上路:事件流

下路:触摸事件

所需事件知识点分布如下图:

(查看大图:右键新标签中打开)掌握了上边的知识点后,就是在长按功能里边的应用了。

别急~

长按功能原理分析一波:

所谓的长按其实就是手指按下去,不移动,超过一定时间才把手指拿开的一个过程(我说的好有道理哈哈哈。然后听到一片同一个声音:废话!!)。

而在这个过程中,正好是触摸的三个事件。

监听手指按下去后是否有移动,就该touches上场了,监听他的clientX,clientY只要没变就是没移动。

并且在这个过程中,还会不时地有地方的英雄冒出来干扰我们补兵。那就是一个手机自带的效果了:

  长按时,在移动端触摸文字,(至少ios里)会出现选择文字等干扰我们的真正功能,用了preventDefault()这个属性后就没有了。

纸上谈兵是没用的额,直接上长按功能代码

为了不必要的麻烦(其实就是我懒得写),把多余的其他代码删掉了,所以不要惊讶export default里边为什么只有mounted。

<script>
  let x = 0,
      y = 0,
      z = 0,
      timer1 = null;
  export default {
    mounted(){
      let oDiv = document.getElementById(‘canvas‘);
      oDiv.addEventListener("touchstart", function(e) {
          if (e.preventDefault) e.preventDefault();
          else e.returnValue = false;
          if (e.touches.length > 1) {
            return false;
          }
          z = 0;
          timer1 = setTimeout(function() {
            z = 1;
          }, 500);
          x = e.touches[0].clientX;
          y = e.touches[0].clientY;
      }, false);
      oDiv.addEventListener("touchmove", function(e) {
          if (e.preventDefault) e.preventDefault();
          else e.returnValue = false;
          if (x != e.touches[0].clientX || y != e.touches[0].clientY) {
            clearTimeout(timer1);
            return false;
          }
      }, false);
      oDiv.addEventListener("touchend", function(e) {
        if (e.preventDefault) e.preventDefault();
        else e.returnValue = false;
        if (z != 1) {
          clearTimeout(timer1);
          x = 0;
          y = 0;
          return false;
        } else if(z=1){
          x = 0;
          y = 0;
          z = 0;
          /* 到这里已确定触发了长按事件,接下来执行长按后要做的其他事情 */
        }
      }, false);
    }
  }
</script>

哎呀,我怎么可能直接甩了代码扭头就走呢!接下来请看~

讲解版本的代码

<script>
  let x = 0,//用于记录clientX
      y = 0,//用于记录clientX
      z = 0,//用于判断,是否是已按住并超过了设定时间。
      timer1 = null;//用于定时器
  export default {
    mounted(){
      let oDiv = document.getElementById(‘canvas‘);
      // 因为长按事件要加在div#canvas上的,如果事件是任何地方的话,就是document

      /* 添加touchstart,手指触摸事件 */
      oDiv.addEventListener("touchstart", function(e) {
          /* 阻止默认事件,其实这里ie的兼容写法returnValue没必要*/
          if (e.preventDefault) e.preventDefault();
          else e.returnValue = false;
          /* 移动时触发touchmove导致多个touches对象,所以可以直接跳出*/
          if (e.touches.length > 1) {
            return false;
          }
          /* 这里有历史渊源的,是第二次点击的时候,把z的值还原。*/
          z = 0;
          /* 手指一旦触摸屏幕,就开启一个倒计时定时器timer1 */
          timer1 = setTimeout(function() {
            z = 1; // 如果倒计时结束还没有清楚定时器的话,就把z赋值为1,这样,当判断z=1就说明按住屏幕的时间达到了开发者设定的长按时间。也就是满足了长按事件
          }, 500);
          /* 手指一旦触摸屏幕,要立即做的第二件事:记录触摸时的点的位置,并存在x,y两个变量里*/
          x = e.touches[0].clientX;
          y = e.touches[0].clientY;
      }, false);

      /* 绑定第二个事件touchmove,手指在屏幕上连续滑动时连续地触发*/
      oDiv.addEventListener("touchmove", function(e) {
          if (e.preventDefault) e.preventDefault();
          else e.returnValue = false;
          /*判断,因为每次手指移动会连续触发touchmove,也就会不停的往event事件对象里边添加“跟踪触摸属性touches”*/
          //这个属性是一个数组,每次新添加的都会在最前边。所以每次获取数组里边的第一个对象对应的clientX和clientY,就是实时的移动点的位置
          //找这个点的作用,就是为了监听用户,是否按住还移动了。如果移动了,那不能算长按事件(不过这个也看产品需求,如果按住也要触发长按规定那个逻辑的话,这不要判断)
          if (x != e.touches[0].clientX || y != e.touches[0].clientY) {
            // 具体的判断方法,还记得touchstar那里已经记录了‘起跑点‘了,只要和x,y的值进行比较,与两个的值有任意一个不等,就是移动了。
            // 那么移动的话,先要清除事先埋伏的定时器timer1.要不然,虽然不是长按事件但是倒计时还在进行中。
            clearTimeout(timer1);
            return false;//除掉‘后患‘后,安心的结束本次用户的触摸事件监听。
          }
      }, false);

      /* 添加第三个触摸事件touchend,这个事件的场景就是用户手指从屏幕拿开时触发*/
      oDiv.addEventListener("touchend", function(e) {
        if (e.preventDefault) e.preventDefault();
        else e.returnValue = false;
        /* 上文已经介绍,当用户拿开的时候,只要判断用户从点击到拿开的时间。而记录时间长度比较麻烦,所以当时用了定时器,设定了一个我们想要的时间,时间到了就改变一个状态值z,所以这里我们只要判断z是否被改变即可*/
        if (z != 1) {
          /* 如果用户手指头拿开的时候,z还是0,即不等于1,说明定时器还没被触发,也就说明没有达到长按的时间,那么不用期待了,同touchmove寿终正寝时要做的一样,清除定时器即可。*/
          clearTimeout(timer1);
          /* 但是,touchend和touchmove还有一点不一样的,touchend是end(废话),touchmove不管move多少次,最终手指总要从屏幕拿开的,这就是他的关键点。而拿开就是结束,结束,是整个这次触摸生命过程的结束。*/
          /* 所以,end还要做的事是初始化,是还原。他需要把x,y的值归为原始。以为了下次再次触发touchstart时做准备。好感人的故事。*/
          x = 0;
          y = 0;
          return false;//然后安心的“死去”。
        } else if(z=1){
          /* 如果,触发了长按事件,终于触发了长按事件!*/
          /* 他还是不能得意忘形,在大展宏图之前,还是要做点准备,打扫一下战场,将各个变量初始化 */
          x = 0;
          y = 0;
          z = 0;

          /* 然后,他才能开心的做自己计划已久的事业:执行长按后要做的其他事情 */
          /* 是什么事情呢? 五点半了,吃饭。*/
        }
      }, false);
    }
  }
</script>

奥,对了还有个现象,在于vue中的swiper一同食用时,长按住并且滑动会触发上/下翻页。如果touchmove里边还要有什么动作的话,加上swiper体验很不好。

2018-07-07  17:35:31

原文地址:https://www.cnblogs.com/padding1015/p/9277922.html

时间: 2024-08-15 16:24:40

JS案例 - 基于vue的移动端长按手势的相关文章

追求极致的用户体验ssr(基于vue的服务端渲染)

首先这篇博客并不是ssr建议教程,需要ssr入门的我建议也不要搜索博客了,因为官网给出了详细的入门步骤,只需要step by step就可以了,这篇博客的意义是如何使用ssr,可能不同的人有不同的意见,我舍弃了ssr中的vuex和vue-router增加了redis,serverfetch等等实现了适合自己公司的业务,个人认为并不是所有的东西都值得吸收,对我来说我能用到的只是ssr将vue生成一个html和对应的js. 虾面我们来看看什么是服务端渲染? 官网给出的解释: Vue.js 是构建客户

基于VUE.JS的移动端框架Mint UI

Mint UI GitHub:github.com/ElemeFE/mint 项目主页:mint-ui.github.io/# Demo:elemefe.github.io/mint- 文档:mint-ui.github.io/docs/# 由饿了么前端团队推出的 Mint UI 是一个基于 Vue.js 的移动端组件库.自 6 月初开源以来,根据社区和团队内部的反馈,修复了一些 bug 并新增了部分组件,于本周发布了 0.2.0 版本.本文介绍如何从零开始构建一个使用 Mint UI 的 Vu

基于vue的nuxt框架cnode社区服务端渲染

nuxt-cnode 基于vue的nuxt框架仿的cnode社区服务端渲染,主要是为了seo优化以及首屏加载速度 线上地址 http://nuxt-cnode.foreversnsd.cngithub地址 https://github.com/Kim09AI/nu... 技术栈 vue vue-router vuex nuxt axios simplemde ES6/7 stylus 目录结构 ├─npm-shrinkwrap.json ├─nuxt.config.js # nuxt配置文件 ├

如何搭建一个基于 Egg + Webpack + Vue 的服务端渲染工程项目呢?

如何搭建一个基于 Egg + Webpack + Vue 的服务端渲染工程项目呢? 项目你可以通过 easywebpack-cli 直接初始化即可完成或者clone egg-vue-webpack-boilerplate.下面说明一下从零如何搭建一个Egg + Webpack + Vue 的服务端渲染工程项目. 通过 egg-init 初始化 egg 项目 egg-init egg-vue-ssr // choose Simple egg app 安装 easywebpack-vue 和 egg

《基于Vue.js的Web前端应用研究》文献阅读(十五)

一.基本信息 标题:基于Vue.js的Web前端应用研究 时间:2017 来源:科技与创新 关键词:Web前端:Vue.js:JavaScript组件:Vue框架 二.研究内容 1.主要内容: 随着互联网的迅猛发展,用户对Web前端的使用体验.交互操作流程.外观有了更高的要求.特别是Web系统中越来越多的数据处理和业务逻辑开始偏向前端,导致Web前端工作量扩大,代码量增加.如果仍然采用传统的方式开发设计Web前端,会导致前期开发度和后期维护难度增大,可扩展性变差.为了提高开发效率和代码复用率,越

优秀的基于VUE移动端UI框架合集

1. vonic 一个基于 vue.js 和 ionic 样式的 UI 框架,用于快速构建移动端单页应用,很简约,是我喜欢的风格 star 2.3k 中文文档 在线预览 2.vux 基于WeUI和Vue(2.x)开发的移动端UI组件库 star 10k 基于webpack+vue-loader+vux可以快速开发移动端页面,配合vux-loader方便你在WeUI的基础上定制需要的样式. 中文文档 在线预览 3.Mint UI 由饿了么前端团队推出的 Mint UI 是一个基于 Vue.js 的

JS案例之5——移动端触屏滑动

移动端触屏滑动的效果其实就是图片轮播,在PC的页面上很好实现,绑定click和mouseover等事件来完成.但是在移动设备上,要实现这种轮播的效果,就需要用到核心的touch事件.处理touch事件能跟踪到屏幕滑动的每根手指. 以下是四种touch事件 touchstart:     //手指放到屏幕上时触发 touchmove:      //手指在屏幕上滑动式触发 touchend:    //手指离开屏幕时触发 touchcancel:     //系统取消touch事件的时候触发,这个

一次基于Vue.Js的用户体验优化

.mytitle { background: #2B6695; color: white; font-family: "微软雅黑", "宋体", "黑体", Arial; font-size: 18px; font-weight: bold; height: 25px; line-height: 25px; margin: 15px 0 !important; padding: 5px 0 5px 20px; width: 97% } .arti

基于Vue.js 2.x系列的后台管理系统解决方案

基于Vue.js 2.x系列 + Element UI 的后台管理系统解决方案. github地址:https://github.com/lin-xin/manage-systemdemo地址:http://work.fengdb.com功能包括:Element UI登录/注销表格表单图表富文本编辑器markdown编辑器图片拖拽/裁剪上传支持切换主题色