这里我们直接使用scrollIntoView
方法
该方法将调用它的元素滚动到浏览器窗口的可见区域
语法
element.scrollIntoView(); // 等同于element.scrollIntoView(true)
element.scrollIntoView(alignToTop); //布尔参数
element.scrollIntoView(scrollIntoViewOptions); //对象参数
组件
分析一下功能就知道很简单了。
首先需要一个通讯录列表,其次是字母列表。
字母列表很简单。
第一种方法:直接用fromCharCode
,for循环遍历拿到26个英文字母。
// 获取26个英文字母大写
for (var i = 0; i < 26; i++) {
this.letter.push(String.fromCharCode(65 + i))
}
但是这样的做法,有一个坏处就是,如果通讯录没有这么多呢?
换句话说,如果通讯录只有ABCDEFG这几个首字母的联系人,你把26个都弄上去有点不太合适。
第二种方法:也是相对简单的,直接从通讯录列表拿到字母。当然,这种方法需要后端给你对应的数据结构。并且得让他给你按首字母排序好,毕竟能少一事少一事。什么?他不干?打一顿他就听话了。
当然,我给出的数据结构你可以参考:
const peoArray = [
{
key: "A",
list: [
{
name: "安吉",
},
{
name: "安吉",
},
],
},
{
key: "B",
list: [
{
name: "爸爸",
},
{
name: "芭比",
},
],
},
{
key: "C",
list: [
{
name: "蔡徐坤",
},
{
name: "蔡徐坤",
},
],
},
]
直接上代码
<template>
<div id="letterPeo">
<!-- 导航栏 -->
<nav class="navBar" v-if="navBar" :style="{ height: navBarHeight }">头部导航栏</nav>
<!-- 字母检索 -->
<div class="letter">
<div v-for="(item, index) in letter" :key="index" @click="scrollOn(item, index)">
{{ item }}
</div>
</div>
<!-- 通讯录列表 -->
<div class="peoBox">
<div class="peo" ref="box">
<div
v-for="(item, index) in peoArray"
:key="index"
@click="onSelect(item, index)"
>
<p class="peoKey" :id="'peo' + item.key">{{ item.key }}</p>
<p class="peolist" v-for="(ele, e) in item.list" :key="e">{{ ele.name }}</p>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
navBar: true, //是否开启头部导航
navBarHeight: "50px", //导航栏高度
letter: [], //字母检索列表
peoArray: [],//通讯录列表
};
},
computed: {},
mounted() {
// 获取26个英文字母大写
// for (var i = 0; i < 26; i++) {
// this.letter.push(String.fromCharCode(65 + i))
// }
// 只获取通讯录字母
this.peoArray.forEach((ele) => {
this.letter.push(ele.key);
});
//因为有导航栏的原因,默认距离顶部一个导航栏的高度
if (this.navBar) this.$refs.box.style.marginTop = this.navBarHeight;
},
methods: {
// 字母检索
scrollOn(item) {
if (this.navBar) this.$refs.box.style.marginTop = 0; // 开启导航后,上边距默认清零
let target = document.getElementById("peo" + item); //获取每个字母通讯录对象
if (target)
target.scrollIntoView({
behavior: "smooth", // 定义动画过渡效果, "auto"或 "smooth" 之一。默认为 "auto"
});
if (this.navBar) this.$refs.box.style.marginTop = this.navBarHeight; //因为有导航栏的原因,所以上边距应该为导航栏的高度
},
// 点击通讯录
onSelect(item, index) {
console.log(item, index);
},
},
};
</script>
<style scoped>
#letterPeo {
width: 100%;
}
/* 导航栏 */
.navBar {
width: 100%;
position: fixed;
text-align: center;
line-height: 50px;
background: #abf0ff;
z-index: 3;
}
/* 字母 */
.letter {
position: fixed;
right: 10px;
top: 15%;
z-index: 2;
}
/* 通讯录 */
.peoBox {
position: relative;
}
.peo {
width: 100%;
overflow-y: scroll;
position: absolute;
}
.peo p{
padding: 0 10px;
}
.peo .peoKey {
margin: 10px 0;
font-size: 12px;
background-color: #f3efef;
}
.peolist {
margin: 20px 0;
}
</style>
完整数据
[
{
key: "A",
list: [
{
name: "安吉",
},
{
name: "安吉",
},
],
},
{
key: "B",
list: [
{
name: "爸爸",
},
{
name: "芭比",
},
],
},
{
key: "C",
list: [
{
name: "蔡徐坤",
},
{
name: "蔡徐坤",
},
],
},
{
key: "D",
list: [
{
name: "打飞机",
},
],
},
{
key: "E",
list: [
{
name: "饿了么",
},
],
},
{
key: "F",
list: [
{
name: "方慧",
},
],
},
{
key: "G",
list: [
{
name: "哥哥",
},
],
},
{
key: "H",
list: [
{
name: "黄老头",
},
],
},
{
key: "I",
list: [
{
name: "ikun",
},
],
},
{
key: "J",
list: [
{
name: "接化发",
},
],
},
{
key: "K",
list: [
{
name: "KFC",
},
],
},
{
key: "L",
list: [
{
name: "刘老根",
},
],
},
{
key: "M",
list: [
{
name: "没读书",
},
],
},
{
key: "N",
list: [
{
name: "牛头人",
},
],
},
{
key: "O",
list: [
{
name: "O泡果奶",
},
],
},
{
key: "P",
list: [
{
name: "嫖老头",
},
],
},
{
key: "Q",
list: [
{
name: "秦三儿",
},
],
},
{
key: "R",
list: [
{
name: "日",
},
],
},
{
key: "S",
list: [
{
name: "塞班",
},
],
},
{
key: "T",
list: [
{
name: "糖糖",
},
],
},
{
key: "U",
list: [
{
name: "U哈哈哈哈",
},
],
},
{
key: "V",
list: [
{
name: "V ME 50",
},
],
},
{
key: "W",
list: [
{
name: "王富贵",
},
],
},
{
key: "X",
list: [
{
name: "喜羊羊",
},
],
},
{
key: "Y",
list: [
{
name: "阳顶天",
},
],
},
{
key: "Z",
list: [
{
name: "赵一曼",
},
],
},
],