vue组件--通讯录
Posted smallcoder
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue组件--通讯录相关的知识,希望对你有一定的参考价值。
简介
在移动端开发中,通讯录是个很常见的需求。
通讯录通常要实现以下功能
- 首字母导航
- 滚动到一定位置首字母固定
布局
通讯录是典型的上下两栏布局,上面是header,下面是内容区,我们这里采用flexbox来实现。
html,body,.page{height: 100%}
.page{display: flex}
.page-header{height: 44px}
.page-content{
flex: 1;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
.navs {
z-index: 2;
position: fixed;
right: 10px;
top: 50px;
bottom: 30px;
text-align: center;
color: #5d9ed3;
font-size: 10px;
display: flex;
flex-direction: column;
justify-content: space-between;
span {
cursor: pointer;
}
}
<div class=‘page‘>
<div class=‘page-header‘>通讯录</div>
<main class=‘page-content‘ ref=‘content‘>
<div class=‘page-navs‘ ref=‘navs‘>
<!--首字母导航区域-->
</div>
<div class=‘page-items‘ ref=‘items‘>
<!--通讯录内容-->
<div class=‘item‘ v-for=‘i in 26‘ :key=‘i‘>
<div class=‘item-head‘>A</div>
<div class=‘item-list‘>
<div class=‘item-head‘>a链家-张带看</div>
<div class=‘item-head‘>a天团tony</div>
</div>
</div>
</div>
</main>
</div>
OK。上面的代码已经足够定义一个页面的雏形,
page-header
高度44,page-content
占据剩余的全局的高度,并做内部的滚动。-webkit-overflow-scrolling: touch
会在容器里面开启高性能滚动。
设置导航
页面布局完成之后,可以初始化导航条了,为了方便起见,我们默认通讯录里面包含了从A到Z的全部姓名。
- 文章默认使用
vue单文件组
件开发,如果您使用其他框架,请自行转换代码
<template>
<div class="page-navs">
<span v-for=‘(item, index) in navs‘ :key=‘item‘>{{item}}</span>
</div>
</template>
<script>
data () {
return {
navs: "abcdefghijklmnopqrstuvwxyz".split("").map(i => i.toUpperCase());
}
}
</script>
建立索引
建立索引实际上是用js操作dom,获取通讯录内容区域内每个首字母出现的位置并存储起来,方便做跳转和滚动监听。
<script>
moutend() {
// 因为要获取dom属性,所以要在组件render后执行
this.$nextTick(()=>{
this.body = this.$refs.content;
const navsEles = [...this.$refs.navs.querySelectorAll("span")]
const itemsEles = [...this.$refs.items.querySelectorAll(".item")]
// 获取导航栏字母的高度信息,方便做点击放大功能
this.navsOffset = navsEles.map(item=>{
return item.offsetTop || 0
})
// 获取通讯录内容区的首字母位置,方便做跳转和滚动监听
this.itemsOffset = itemsEles.map(item=>{
return item.offsetTop || 0
})
})
},
data () {
return {
body: null,
itemsOffset: [],
navsOffset: []
}
}
</script>
监听跳转
监听跳转比较简单,在 .page-navs span
标签上绑定click事件即可处理
<template>
<div class="page-navs">
<span v-for=‘(item, index) in navs‘ :key=‘item‘ @click=‘jump(index)‘>{{item}}</span>
</div>
</template>
<script>
methods: {
jump(index) {
// 因为offsetTop属性是相对整个视口,而scrollTop是相对滚动容器,所以需要减去44px(header的高度)
const offset = this.itemsOffset[index] - 44;
this.body.scrollTop = offset;
}
},
data () {
return {
navs: "abcdefghijklmnopqrstuvwxyz".split("").map(i => i.toUpperCase());
}
}
</script>
监听滚动
因为是在page-content元素内部滚动,所以可以通过在该元素上绑定scroll方法监听页面的滚动。局部滚动的好处是组件销毁时事件监听也移除了,不像监听body的滚动还需要在销毁前手动removeEventListenr。
在执行滚动监听之前,我们还需要做两件事情
- 对
itemsOffset
进行分组,划定监听的区间 - 在页面顶部创建一个展示
当前联系人首字母
的组件
// 当前联系人首字母组件
// 在这个组件里面也创建一个列表,用来做滚动的动画
<template>
<div class="first-word">
<div class="acr-list" :style="‘transform: translate3d(0,‘+(currentIndex * -40)+‘px,0);‘">
<div class="item" v-for=‘(item, index) in navs‘ :key=‘index‘>{{item}}</div>
</div>
</div>
</template>
// 对 `itemsOffset` 进行分组,划定监听的区间
mounted() {
this.$nextTick(() => {
let offsetCalc = this.offset.slice();
offsetCalc.forEach((item, index) => {
this.offsetList.push([item, offsetCalc[index + 1]]);
});
});
}
data() {
return {
currentIndex: -1,
offsetList: []
}
}
在准备工作做好之后,就开始监听容器的滚动行为,当滚动到通讯录之中的首字母部分时, 联系人首字母组件
也会自动滚动到里面相应的字母位置。
点击右侧导航,也会触发滚动事件。
// html模板部分
<main class=‘page-content‘ @scroll=‘scroll‘ ref=‘content‘></main>
// js部分
methods: {
scroll() {
this.currentIndex = this.getArea(this.body.scrollTop);
},
getArea(scrollTop) {
// 80是首字母标组件的高度+通讯录首字母的高度
scrollTop += 80;
let index = -1;
for (let i = 0, size = this.offsetList.length; i < size; i++) {
let [start, end] = this.offsetList[i];
if (scrollTop >= start && scrollTop < (end || 999999)) {
index = i;
break;
}
}
return index
},
}
更多
点击右侧导航,有时候还要求在附近显示一个放大的字母,用于提醒点击了那个字母,通过前面获取的 navsOffset ,可以很方便的实现这个需求。至此,整个通讯录功能就基本完成了。
以上是关于vue组件--通讯录的主要内容,如果未能解决你的问题,请参考以下文章