最近公司需求要做一個字母導航聯系人列表,自己有一些思路解決這個問題。由于以前沒有寫過,在做這個需求前,想看看別人都是怎么解決的,于是在網上搜索了一番,找到了一篇文章《一步一步實現字母索引導航欄》來實現這個需求。以下作者都是指該篇文章作者,該篇文章鏈接見文尾。
作者寫的非常詳細,作者用了純js實現,不依賴任何三方庫。作者采用了訂閱--發布的設計模式來實現了這個功能。作者使用設計模式的思想很不錯,并且提供了擴展的能力。但是對于我們的實際需求可能不用做的這么麻煩。總結幾點如下:
1、這種功能一般只有移動端有,pc端幾乎沒見過,所以不必考慮pc端的兼容
2、這個功能可擴展性不是很強,而且每個公司ui都是不同的,都要自己實現,變動大點基本要重寫。所以沒有必要搞個設計模式出來實現這個簡單功能。
3、現在為了提高開發效率,做前端用純js寫代碼的應該不多了。前端比較火的框架和庫就是react、vue、angular所 以我想結合框架來實現這一功能。
于是自己動手實現了一番,本demo用react、vue兩個版本來實現,不要問我為什么不用angular來實現,是不是鄙視angular?那就冤枉啊,因為我壓根就不會angular。
效果圖:
1.gif
因為是移動端:
1、我用了flex布局解決了右邊字母縱向布局,簡化了作者用js動態計算距離的過程。
2、通過監聽原生的touchstart、touchmove、touchend事件獲取當前點到頂部的距離,在根據整個字符串所占的高度可以計算出當前點所處的字符串是什么。
getChar (clientY) {
const charHeight = this.$refs.charBar.offsetHeight / this.charList.length;// 計算沒一個字符高度
const index = Math.floor((clientY - this.boxClientTop) / charHeight); // 獲取當前觸點是第幾個字符串減一
return this.charList[index]; // 取出當前觸摸的字符串
}
3、通過右邊監聽的字符串的變化來執行左邊列表定位。左邊列表在渲染時,每個字母首次渲染時,在前面插入一個標記。在通過scrollIntoView這個屬性來定位。
gotoChar (char) {
if (char === this.lastChar) { // 上一次觸發的字符串儲存起來,如果此次觸發字符串與上次相同,則不執行以下邏輯
return false;
}
this.lastChar = char; // 否則將本次字符串賦值給上一次字符串
if (char === '*') { // 對于特殊字符串處理,如收藏的數據可以用 * 表示
this.$refs.countryList.scrollTop = 0;
} else if (char === '#') { // 不屬于26個字母里的數據可以放在這里如聯系人為數字開頭的
this.$refs.countryList.scrollTop = this.$refs.countryList.scrollHeight;
}
const target = document.querySelector('[data-en="' + char + '"]');
if (target) {
target.scrollIntoView();
}
}
本項目的webpack配置不是實際項目中的配置,只是方便查看效果而建的簡單的項目,本項目數據來自源作者的項目。
git clone https://github.com/keenjaan/alphabetical-index-navigation.git
npm i
npm run vue // 查看vue版本效果
npm run react // 查看react版本效果