vue/js 实现仿通讯录-列表滑动字母索引
2019-09-03 16:26
2301 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_29491885/article/details/100521518
最近写东西刚好遇到如下设计:
要求
- 实现地区按字母排序
- 加上侧边索引
- 点击侧边索引滑动到指定字母列表
- 页面滑动的时候顶栏序列号随之变化
- PC端鼠标悬浮,移动端触屏侧边索引实现以上两个效果
步骤
- 从country.json获取countryList数据
- 提取侧边栏字母并排序
- 将countryList按照字母分类排序
- 对侧边栏进行操作
不废话直接上代码
代码有一丢丢长,如果看不下去可以直接 点击下载源码查看调试
<!-- 选择地区 --> <article class="country" ref="listview" v-show="countryList.length>0" v-cloak> <ul class="country-list"> <li v-for="group in countryList" ref="listGroup"> <h2 class="list-group-title">{{group.title}}</h2> <ul> <li v-for="item in group.items" :class="[{active:phoneCode==item.code},'list-group-item']" @click="phoneCode=item.code"> <span class="name">{{item.name_cn}}</span> <span>(+{{item.code}})</span> </li> </ul> </li> </ul> <ul class="list-shortcut" @click.stop.prevent="onShortcutTouchStart" @touchstart="onShortcutTouchStart" @touchmove.stop.prevent="onShortcutTouchMove" @touchend.stop.prevent="onShortcutTouchEnd"> <li @mouseover.stop.prevent="onMouseover(index)" @mouseout.stop.prevent="onShortcutTouchEnd" :class="[{selected:fixedTitle==item},'item']" v-for="(item,index) in shortcut">{{item}}</li> </ul> <div class="selected-shortcut" v-show="isTouch">{{fixedTitle}}</div> <div class="list-fixed" v-show="fixedTitle" ref="fixed">{{fixedTitle}}</div> </article> <script src="./js/jquery-3.2.1.min.js"></script> <script src="./js/vue.min.js"></script> <script type="text/javascript"> $(function() { var country = new Vue({ el: ".country", data: { isTouch:false, countryList: [], shortcut: [], phoneCode: '93', touch: {}, listHeight: [], scrollY: -1, currentIndex: 0, diff: -1, fixedTop: -1 }, created() { this.getCountryList(); }, computed: { fixedTitle() { return this.shortcut[this.currentIndex] ? this.shortcut[this.currentIndex] : 'A' } }, mounted() { var _this = this; // 地区选择模块 $('.country').scroll(function() { _this.scrollY = $('.country').scrollTop() }) setTimeout(function() { _this.calculateTotalHeight() }, 20) }, methods: { getCountryList() { var _this = this; $.getJSON('http://mdsApistatic/js/login/country.json', function(res) { // 格式化数据 var map = {}; res.forEach(function(item, index) { var key = item.name_en.slice(0, 1); if (!map[key]) { _this.shortcut.push(key) map[key] = { title: key, items: [] } } map[key].items.push(item); }) // 转为数组 var ret = []; for (var k in map) { var val = map[k]; ret.push(val); } // 排序 ret.sort(function(a, b) { return a.title.charCodeAt(0) - b.title.charCodeAt(0); }); _this.shortcut.sort(function(a, b) { return a 8000 .charCodeAt(0) - b.charCodeAt(0); }); _this.countryList = ret; }) }, onShortcutTouchStart(e) { let anchorIndex = this.shortcut.indexOf(e.target.innerText); this.touch.y1 = e.pageY ? e.pageY : e.touches[0].pageY this.touch.anchorIndex = anchorIndex; this.scrollToIndex(anchorIndex); this.isTouch = true; }, onShortcutTouchMove(e) { this.touch.y2 = e.touches[0].pageY var delta = (this.touch.y2 - this.touch.y1) / 16 | 0 var anchorIndex = parseInt(this.touch.anchorIndex) + parseInt(delta) this.scrollToIndex(anchorIndex); this.isTouch = true; }, onShortcutTouchEnd(){ this.isTouch = false; }, onMouseover(index){ this.touch.anchorIndex = index; this.scrollToIndex(index); this.isTouch = true; }, scrollToIndex(index) { this.$refs.listview.scrollTo(0, this.listHeight[index]) }, calculateTotalHeight() { var list = this.$refs.listGroup var height = 0 this.listHeight.push(height) for (var i = 0; i < list.length; i++) { var item = list[i] height += item.clientHeight this.listHeight.push(height) } } }, watch: { scrollY(newY) { var listHeight = this.listHeight // 当滚动到顶部时, newY<=0 if (newY <= 0) { this.currentIndex = 0 return } // 中间部分滚动 for (var i = 0; i < listHeight.length - 1; i++) { var height1 = listHeight[i] var height2 = listHeight[i + 1] if (!height2 || (newY >= height1 && newY < height2)) { this.currentIndex = i this.diff = height2 - newY return } } // 滚动到底部且newY大于最后一个元素的上限 this.currentIndex = listHeight.length - 1 }, diff(newVal) { var fixedTop = (newVal - 24) < 0 ? newVal - 24 : 0 if (this.fixedTop === fixedTop) { return false; } this.fixedTop = fixedTop this.$refs.fixed.style.transform = `translate3d(-50%,${fixedTop}px,0)` } } }) }) </script>
相关文章推荐
- js实现做通讯录的索引滑动显示效果和滑动显示锚点效果
- vue实现移动端地区城市列表按中文首字母索引
- [Android开发] 在项目中快速实现 列表字母排序滑动索引 功能原理以及过程代码
- Android仿微信实现通讯录字母列表索引
- Andorid使用自定义View实现通讯录,媒体文件等等的ListView的字母索引
- 自定义view实现字母索引列表
- Android实现通讯录功能,排序+字母索引
- Windows Phone 7 LongListSelector控件实现分类列表和字母索引
- Android 自定义 View 实现通讯录字母索引(仿微信通讯录)
- Andorid学习笔记 :实现对ListView列表数据添加字母索引效果
- 数据列表实现方式(基于Vue.js封装)
- vue.js + element UI实现表格、列表的拖动 推拽效果
- Android获取通讯录联系人,右侧字母滑动索引
- Vue.js实现列表清单的操作方法
- Android获取通讯录联系人,右侧字母滑动索引
- 支持搜索的智能字母索引列表(可拓展成城市列表或者通讯录列表)
- Vue.js优雅的实现列表清单
- Windows Phone 7 LongListSelector控件实现分类列表和字母索引
- 【前端】Vue.js实现网格列表布局转换
- Android自定义控件5----继承View通讯录索引功能之1初始化显示字母列表