combox默认选中第一个_微操作:页面上下左右选中元素

90e4707b3cfd77c944cc0017c499b2cb.png

前言

纯粹是因为无聊吧,然后就是突发奇想。

我以前开发过web端的收银系统。之前更早的时候也是做过零售软件方面的实施,通常在门店的时候收银员为了更为快速的去收银,是很少会去用鼠标的。都是键盘解决。但是web操作系统页面有一个问题。就是你的通过tab等方式其实不是很方便。然后我们还有商品列表也需要通过键盘方式选中返回。如果通过鼠标,在一些门店每天都是几万的销售额中,是非常累人,且效率低下的。这次开发的这个插件也是为了解决这方面的问题。

目前做到了基本的上下左右,属于初步的完成。未经业务实战。但是我想还是比较OK的。

原理:

首先,我们想要键盘上面操作选中dom元素。有本身的tap,上下左右等等,也可以使用tabindex,方式。但是这些都无法说使得操作统一方便。规则较为混乱,并且我们都知道div是么有焦点这个状态的。

那么我们想要实现的情况下,那么就需要自己造轮子了。我们自己来定义并且实现这一套规则。

1、监听键盘的上下左右

2、随着元素的上下左右进行数据移动。

吐槽一下,如果是jquery时代,怕是要麻烦很多。

实现左右移动

左右移动其实很简单,我们只要操作元素的数组的index对应的增加减就可以了。所以代码简单的不行。

同理,我们要操作元素的上下也可以这样实现。但是我的目的是要普适性的实现。那么左右我们是根据既定规则来实现的。

定义插入的数组的元素结构

// 设置绑定的初始数据this.dhtSetList({  bindData: value, // 绑定数据  self: this, // 本身  select: false, // 是否被选中})复制代码

这里其实比较简单能看出来,第一个是绑定的数据。第二个是vue当前实例本身。第三个就是状态,可以不管。

插入的顺序决定了左右移动的顺序

上下移动

上下移动最麻烦的是我们不能按数组的index进行移动。要根据元素本身的上下位置进行移动。

代码原理讲解:

1、过滤同级别元素

2、上过滤掉比自己低的,下过滤比自己高的

3、对元素的高低进行排序,上最小,下最小的元素。

4、如果上下存在一样的Y轴数据,那么比较X大小,得到最小X进行返回,X如果还有多个,那么默认返回第一个

// 上下移动topOrbottomMove(type) {  let currentIndex = this.lastTimeLi() // 上一次的index,也是当前的index  const list = this.list  // 当前  const currentLi = list[currentIndex]  const currentLiDom = currentLi.self.$el.getBoundingClientRect()  const currentY = currentLiDom.y  const currentX = currentLiDom.x  const relativeList = []  list.forEach((item, index) => {    const { y, x } = item.self.$el.getBoundingClientRect()    relativeList.push({      li: item,      y: currentY - y,      x: Math.abs(currentX - x),      index,    })  })  // 过滤通等级元素  const eliminate = relativeList.filter(item => item.y !== 0)  if (type === 'top') {    // 往上过滤比自己低的    const topEliminate = eliminate.filter(item => item.y > 0)    if (topEliminate.length === 0) {      // 最终发送确认值      this.sendEmit({ item: list[currentIndex], index: currentIndex })    } else {      topEliminate.sort((a, b) => a.y - b.y)      const xArr = topEliminate.filter(item => item.y === topEliminate[0].y)      if (xArr.length > 1) {        xArr.sort((a, b) => a.x - b.x)        this.sendEmit({ item: xArr[0], index: xArr[0].index })      } else {        this.sendEmit({ item: xArr[0], index: xArr[0].index })      }    }  }  if (type === 'bottom') {    // 往下过滤比自己高的    const bottomEliminate = eliminate.filter(item => item.y < 0)    if (bottomEliminate.length === 0) {      // 最终发送确认值      this.sendEmit({ item: list[currentIndex], index: currentIndex })    } else {      bottomEliminate.sort((a, b) => b.y - a.y)      const xArr = bottomEliminate.filter(item => item.y === bottomEliminate[0].y)      if (xArr.length > 1) {        xArr.sort((a, b) => a.x - b.x)        this.sendEmit({ item: xArr[0], index: xArr[0].index })      } else {        this.sendEmit({ item: xArr[0], index: xArr[0].index })      }    }  }},复制代码

总结

基本原理其实挺简单的。

注意我这里为了保证每个子组件用了provide、inject方式进行数据分发。示例中是单独定义了一个子的组件,但是只要根据规则传递数据,那么也就没有什么问题了。

最后,咱给小编:

1. 点赞+评论

2. 点头像关注,转发给有需要的朋友。

谢谢!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值