简介

在移动端开发中,通讯录是个很常见的需求。

通讯录通常要实现以下功能

  • 首字母导航
  • 滚动到一定位置首字母固定

在线通讯录demo

布局

通讯录是典型的上下两栏布局,上面是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。

在执行滚动监听之前,我们还需要做两件事情

  1. itemsOffset 进行分组,划定监听的区间
  2. 在页面顶部创建一个展示 当前联系人首字母 的组件
// 当前联系人首字母组件
// 在这个组件里面也创建一个列表,用来做滚动的动画
<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组件--通讯录的更多相关文章

  1. vue组件

    分享出来让思路更成熟. 首先组件是 Vue.js 最强大的功能之一. 可以减少很多的工作量,提高工作效率. 编写一个可复用性的组件,虽然官网上也有.... 编写可复用性的vue组件 具备一下的几个要求 ...

  2. vue组件的配置属性

    vue组件的声明语法: Vue.component('component-name',{ template:'<p>段落{{prop1}} {{prop2}}</p>', da ...

  3. vue组件,撸第一个

    实现此例您可以学到: vue-cli的基本应用 父组件如何向子组件传递值 单文件组件如何引入scss v-on和v-for的基础应用 源码下载 一.搭建vue开发环境 更换镜像到cnpmnpm ins ...

  4. vue组件最佳实践

    看了老外的一篇关于组件开发的建议(强烈建议阅读英文原版),感觉不错翻译一下加深理解. 这篇文章制定一个统一的规则来开发你的vue程序,以至于达到一下目的. 1.让开发者和开发团队更容易发现一些事情. ...

  5. JS组件系列——又一款MVVM组件:Vue(二:构建自己的Vue组件)

    前言:转眼距离上篇 JS组件系列——又一款MVVM组件:Vue(一:30分钟搞定前端增删改查) 已有好几个月了,今天打算将它捡起来,发现好久不用,Vue相关技术点都生疏不少.经过这几个月的时间,Vue ...

  6. vue组件大集合 component

    vue组件分为全局组件.局部组件和父子组件,其中局部组件只能在el定义的范围内使用, 全局组件可以在随意地方使用,父子组件之间的传值问题等. Vue.extend 创建一个组件构造器 template ...

  7. 【Vue】详解Vue组件系统

    Vue渲染的两大基础方式 new 一个Vue的实例 这个我们一般会使用在挂载根节点这一初始化操作上: new Vue({ el: '#app' }) 注册组件并使用—— 全局注册 通过Vue.comp ...

  8. 关于vue组件的一个小结

    用vue进行开发到目前为止也有将近一年的时间了,在项目技术选型的时候隔壁组选 react的时候我们坚持使用vue作为前端的开发框架.虽然两者思想上的差异不大,但是vue的语法在代码的可读性以及后期的维 ...

  9. Vue组件基础用法

    前面的话 组件(Component)是Vue.js最强大的功能之一.组件可以扩展HTML元素,封装可重用的代码.根据项目需求,抽象出一些组件,每个组件里包含了展现.功能和样式.每个页面,根据自己所需, ...

随机推荐

  1. 多个Firefox共存&&彻底关闭自动更新

    安装 0x001 下载好要安装Firefox的版本 可到Firefox官方仓库下载 https://ftp.mozilla.org/pub/firefox/releases/ 我下载的是42和56版 ...

  2. 洛谷 P4011 孤岛营救问题【最短路+分层图】

    题外话:昨夜脑子昏沉,今早一调试就过了...错误有:我忘记还有墙直接穿墙过...memset初始化INF用错了数...然后手残敲错一个状态一直过不了样例...要是这状态去比赛我简直完了......or ...

  3. FWT背板笔记

    板子 背板子.jpg \(Fwt\)用于解决这样的问题 \[C_i=\sum_{j\bigoplus k=i}A_j\times B_k\] 其中\(\bigoplus\)是一种二元运算符,如\(or ...

  4. PHP类的静态(static)方法和静态(static)变量使用介绍

    PHP类的静态(static)方法和静态(static)变量使用介绍,学习php的朋友可以看下     在php中,访问类的方法/变量有两种方法: 1. 创建对象$object = new Class ...

  5. 调试cnn-Sentence-Classifier遇到的问题

    运行train文件训练模型出现了以下错误: train文件在app文件目录下: raw_vectors.txt文件则在cnn-Sentence-Classifier目录下: 这是train代码调用re ...

  6. Appium移动自动化测试(一)--Mac安装Appium

    一.Appium安装 1. 直接安装:Appium官网下载:https://bitbucket.org/appium/appium.app/downloads/ 这里mac系统升级到 Sierra后, ...

  7. 小H和密码

    链接:https://www.nowcoder.com/acm/contest/72/B来源:牛客网 题目描述     小H在击败怪兽后,被一个密码锁挡住了去路     密码锁由N个转盘组成,编号为1 ...

  8. [图解tensorflow源码] MatMul 矩阵乘积运算 (前向计算,反向梯度计算)

  9. BUAA OO 2019 第一单元作业总结

    目录 总 架构 Controller​ Model​ 输入处理 代码静态分析 行数 方法复杂度 UML​ 类图 优点 缺点 坑 输入 非法的空白字符 输入的简并处理 运算 浅拷贝 可变类型与不可变类型 ...

  10. C++ 容器类型成员

    类型别名   iterator 此容器类型的迭代类型 const_iterator 可以读取元素,但不能修改元素的迭代器类型 size_type 无符号整数类型,足够保存此种容器类型最大可能容器的大小 ...