Open EasonYou opened 6 years ago
公司需求要是实现一个首字母索引的功能,类似于微信通讯录那样的效果。在多次在github上查找都没有找到类似的实现,所以自己就简单地实现了一把。
主要的dom解构分两大块,一大块是索引内容的列表,一大块是字母列表
<div class="index-lists-wapper" ref="scrollTarget"> <div class="index-lists-content" ref="scrollWapper"> <div v-for="(item, index) in finalDatas" :data-character="item.character" :key="index" class="list-item"> </div> </div> </div> <div class="side-index-wapper" ref="sideIndexWapper" @mousedown="bindSideItemMouseDownEvent" @mousemove="bindSideItemMouseMoveEvent" @mouseup="bindSideItemMouseUpEvent"> <div v-for="(item, index) in finalCharacters" :key="index" class="side-index-item"> </div> </div> </div>
在内容索引列表上,绑定上data-set,好在后面做查找对比。 因为要实现按住滑动还能查找的功能,在字母列表上做了事件代理,减少dom的事件绑定。
data-set
在mousedown的情况下,设置一个标志位为isMouseDown。在mousemove的时候切换查找的字母,最后mouseup的时候设标志位为false 在这里有一个问题就是在超出区域范围,会使得mouseup无效,所以在created的时候绑定了下windows,解决超出范围无效的情况。
mousedown
isMouseDown
mousemove
mouseup
false
created
bindSideItemMouseDownEvent (e) { this.isMouseDown = true this.lastTime = new Date() this.switchCharacter(e) }, bindSideItemMouseMoveEvent (e) { const nowTime = new Date() if (nowTime - this.lastTime > this.throttleTime) { this.lastTime = nowTime this.switchCharacter(e) } }, bindSideItemMouseUpEvent (e) { this.isMouseDown = false this.modalFlag = false } // created created () { const self = this document.addEventListener('mouseup', () => { self.isMouseDown = false self.modalFlag = false }) }
接下来是switchCharacter方法
switchCharacter
switchCharacter (e) { if (this.isMouseDown) { // 判断是否可以触发判断,触发条件是是否代理到了side-index-item类的dom // 并返回这个字母 let character = this.isCanTrigger(e) // 如果这个字母变了的话,就可以改变查看的索引字母了 if (character && character !== this.character) { this.character = character } } } // isCanTrigger (e) { let target = e.target let flag = false // while循环查找是否有side-index-item while (target) { if (target && target.className === 'side-index-item') { flag = true break } target = target.parentNode } if (!flag) { return false } // 这里 -2 是因为有个modal(字母弹出层)还有一个text dom // 因为是按循序排序,所以找出index,就可以找出对应的首字母 let index = Array.from(this.$refs.sideIndexWapper.childNodes).indexOf(target) - 2 return this.finalCharacters[index] }
最后只要watch索引字母character就可以做滚动了
watch
character
watch: { character (newVal, oldVal) { // 获取traget是为了滚动 // 获取wapper是为了获取他的childNodes就是列表项 const scrollTarget = this.$refs.scrollTarget const scrollWapper = this.$refs.scrollWapper const scrollItems = Array.from(scrollWapper.childNodes) let offsetTop // 遍历查找,找到就跳出便利,取得目标dom的offsetTop scrollItems.some((item) => { if (item.className === 'list-item' && item.dataset.character === newVal) { offsetTop = item.offsetTop return true } }) // 进行滚动 scrollTarget.scrollTop = offsetTop === undefined ? scrollTarget.scrollTop : offsetTop } }
到此位置就是整个索引的主要流程,具体的代码可以看项目vue-index。
Vue-index 一个vue的字母索引组件
前言
公司需求要是实现一个首字母索引的功能,类似于微信通讯录那样的效果。在多次在github上查找都没有找到类似的实现,所以自己就简单地实现了一把。
dom结构
主要的dom解构分两大块,一大块是索引内容的列表,一大块是字母列表
在内容索引列表上,绑定上
data-set
,好在后面做查找对比。 因为要实现按住滑动还能查找的功能,在字母列表上做了事件代理,减少dom的事件绑定。字母列表事件处理
在
mousedown
的情况下,设置一个标志位为isMouseDown
。在mousemove
的时候切换查找的字母,最后mouseup
的时候设标志位为false
在这里有一个问题就是在超出区域范围,会使得mouseup
无效,所以在created
的时候绑定了下windows,解决超出范围无效的情况。接下来是
switchCharacter
方法最后只要
watch
索引字母character
就可以做滚动了到此位置就是整个索引的主要流程,具体的代码可以看项目vue-index。