您的位置:首页 > Web前端 > Vue.js

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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: