IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 如何做字母导航(手机通讯录) -> 正文阅读

[JavaScript知识库]如何做字母导航(手机通讯录)

??最近项目开发中有个需求是做形如手机通讯录的字母导航,如下图示例那种。


请添加图片描述


??最近是用智能小程序开发的项目,所以就贴一下智能小程序实现的代码,大家可以根据自己的需要更改样式或者逻辑。目前自测了是没有问题的。

??首先是一个函数,这个函数是实现,把中文开头的拼音的首字母提出,比如上面图片里的S;把英文开头的首字母提出;把数字等归为"#"。
??这里我当时卡壳了半天,思维有所受限,还是带我的导师分分钟搞定的,哈哈,夸张了一下。

pySegSort(arr, dataIndex) {
    if (!String.prototype.localeCompare) return null;
    let letters = '#ABCDEFGHJKLMNOPQRSTWXYZ'.split('');
    let zh = '阿八嚓哒妸发旮哈讥咔垃痳拏噢妑七呥扨它穵夕丫帀'.split('');
    let segs = [];
    let zh_arr = [];
    let en_arr = [];
    arr.forEach((item) => {
        let name = dataIndex ? item[dataIndex] : item;
        if (/[a-zA-Z]/.test(name.charAt(0))) {
            en_arr.push(item);
        } else {
            zh_arr.push(item);
        }
    })
    letters.forEach((letter, i) => {
        let curr = { letter, data: [] };
        zh_arr.forEach(item => {
            let name = dataIndex ? item[dataIndex] : item;
            if ((!zh[i - 1] || zh[i - 1].localeCompare(name) <= 0) && name.localeCompare(zh[i]) === -1) {
                curr.data.push(item);
            }
        });
        if (curr.data.length) {
            segs.push(curr);
            curr.data.sort((a, b) => (dataIndex ? a[dataIndex].localeCompare(b[dataIndex]) : a.localeCompare(b)));
        }
    });

    en_arr.forEach((item) => {
        let name = dataIndex ? item[dataIndex] : item;
        let en = name.charAt(0).toUpperCase();
        let index = segs.findIndex(({ letter }) => letter === en)
        if (index > -1) {
            segs[index].data.push(item);
        } else {
            segs.push({
                letter: en, data: [item]
            })
        }
    })
    return segs.sort((a, b) => a.letter < b.letter ? -1 : 1);
},

??然后我mock了一堆假数据,复制到 js 里又改了改,并传入函数中执行,如下是我的假数据和函数执行后打印出来的结果。
let arr = [
    {
        "name": "12345678989"
    },
    {
        "name": "hhh"
    },
    {
        "name": "地这究图选由"
    },
    {
        "name": "42245678989"
    },
    {
        "name": "支高动经可接"
    },
    {
        "name": "www"
    },
    {
        "name": "革百看回压采"
    },
    {
        "name": "然场干总每起"
    },
    {
        "name": "d切"
    },
    {
        "name": "知再议速看青"
    },
    {
        "name": "哈哈"
    },
    {
        "name": "术着白治志接"
    },
    {
        "name": "斗用重从水品"
    },
    {
        "name": "入治说约开图"
    },
    {
        "name": "道与需走应任"
    },
    {
        "name": "程中标以县林"
    },
    {
        "name": "器者红北门正"
    },
    {
        "name": "准果素造展内"
    },
    {
        "name": "区线志反从说"
    },
    {
        "name": "见题通般行越"
    },
    {
        "name": "间此代之委准"
    },
    {
        "name": "用何极段织林"
    },
    {
        "name": "阶都实快极共"
    },
    {
        "name": "都京米应今下"
    },
    {
        "name": "开车也观车算"
    },
    {
        "name": "已入金本无划"
    },
    {
        "name": "压取它应便关"
    },
    {
        "name": "当无农快品导"
    },
    {
        "name": "起公维业等民"
    },
    {
        "name": "命素府利华新"
    },
    {
        "name": "教想适治器该"
    },
    {
        "name": "查需国价政增"
    },
    {
        "name": "管起来西毛般"
    },
    {
        "name": "广资接最更千"
    },
    {
        "name": "来命确两界地"
    },
    {
        "name": "政团铁层状很"
    },
    {
        "name": "长西信两效加"
    },
    {
        "name": "般则就级好示"
    },
    {
        "name": "方际出产党满"
    },
    {
        "name": "思革青许龙所"
    },
    {
        "name": "从加月引成支"
    },
    {
        "name": "立此验解包众"
    },
    {
        "name": "受器整广速物"
    },
    {
        "name": "已记却界六明"
    },
    {
        "name": "么所指往通情"
    },
    {
        "name": "型界新习此满"
    },
    {
        "name": "争算原究感府"
    },
    {
        "name": "求米当标得任"
    },
    {
        "name": "西响所酸即和"
    },
    {
        "name": "最具展小量目"
    },
    {
        "name": "类再复际方也"
    },
    {
        "name": "到手了议常入"
    }
];
console.log(this.pySegSort(arr, "name"));

在这里插入图片描述

??然后可以把数据更新到data里的list里,再根据数据格式去.swan文件渲染数据,这里我是用了智能小程序的scroll-view组件来实现滑动和字母定位,先粘一下代码:

<view class="container">
    <scroll-view
        class="scroll-view"
        scroll-y
        scroll-top="{= scrollTop =}">
        <block s-for="item,index in list">
            <view class="letter">{{item.letter}}</view>
            <view id="{{item.letter}}" s-for="c,i in item.data">
                <view class="part">{{c.name}}</view>
            </view>
        </block>
    </scroll-view>
    <view class="navigation">
        <text s-for="item,index in letters" bindtap="scrollToTop" data-id="{{item}}">{{item}}</text>
    </view>
</view>

??其中有一个scrollToTop点击事件,可以通过这个事件更改scrollTop中的值,进而达到点击右侧字母时,左侧内容定位到同样字母开头的位置,如下:

scrollToTop(e) {
    let arr = [...this.data.list];
    let l = [];
    let count = 0;
    let len = 0;
    for (let i = 0; i < arr.length; i++) {
        l.push(arr[i].letter);
        if (arr[i].letter === "#" && e.target.dataset.id === "#") {
            count = len = 0;
        } else if ((arr[i].letter < e.target.dataset.id) || (arr[i].letter === "#" && e.target.dataset.id !== "#")) {
            count += arr[i].data.length;
            len++;
        } else {
            break;
        }
    }
    //注意这里的50.5是我一条数据的高度,37.5是字母的高度
    if (l.indexOf(e.target.dataset.id) !== -1) {
        this.setData({
            scrollTop: count * 50.5 + 37.5 * len
        })
    }
},

??这样就ok了,下面粘贴一下效果图:

在这里插入图片描述

??css样式可以根据自己需要去写哈。比如字母那加个粘性定位啥的。

??js文件的详细代码如下,在实际项目开发,list数据可以调用后端接口获取一下再用this.setData更新。

Page({
    data: {
        list: [],
        //字母导航表
        letters: ['#', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
        scrollTop: 0,
    },
    /**
     * 将汉字转为字母
     */
    pySegSort(arr, dataIndex) {
        if (!String.prototype.localeCompare) return null;
        let letters = '#ABCDEFGHJKLMNOPQRSTWXYZ'.split('');
        let zh = '阿八嚓哒妸发旮哈讥咔垃痳拏噢妑七呥扨它穵夕丫帀'.split('');
        let segs = [];
        let zh_arr = [];
        let en_arr = [];
        arr.forEach((item) => {
            let name = dataIndex ? item[dataIndex] : item;
            if (/[a-zA-Z]/.test(name.charAt(0))) {
                en_arr.push(item);
            } else {
                zh_arr.push(item);
            }
        })
        letters.forEach((letter, i) => {
            let curr = { letter, data: [] };
            zh_arr.forEach(item => {
                let name = dataIndex ? item[dataIndex] : item;
                if ((!zh[i - 1] || zh[i - 1].localeCompare(name) <= 0) && name.localeCompare(zh[i]) === -1) {
                    curr.data.push(item);
                }
            });
            if (curr.data.length) {
                segs.push(curr);
                curr.data.sort((a, b) => (dataIndex ? a[dataIndex].localeCompare(b[dataIndex]) : a.localeCompare(b)));
            }
        });

        en_arr.forEach((item) => {
            let name = dataIndex ? item[dataIndex] : item;
            let en = name.charAt(0).toUpperCase();
            let index = segs.findIndex(({ letter }) => letter === en)
            if (index > -1) {
                segs[index].data.push(item);
            } else {
                segs.push({
                    letter: en, data: [item]
                })
            }
        })
        return segs.sort((a, b) => a.letter < b.letter ? -1 : 1);
    },
    /**
     * 右侧字母表点击字母滑动到对应首字母开头的数据位置
     */
    scrollToTop(e) {
        let arr = [...this.data.list];
        let l = [];
        let count = 0;
        let len = 0;
        for (let i = 0; i < arr.length; i++) {
            l.push(arr[i].letter);
            if (arr[i].letter === "#" && e.target.dataset.id === "#") {
                count = len = 0;
            } else if ((arr[i].letter < e.target.dataset.id) || (arr[i].letter === "#" && e.target.dataset.id !== "#")) {
                count += arr[i].data.length;
                len++;
            } else {
                break;
            }
        }
        //注意这里的50.5是我一条数据的高度,37.5是字母的高度
        if (l.indexOf(e.target.dataset.id) !== -1) {
            this.setData({
                scrollTop: count * 50.5 + 37.5 * len
            })
        }
    },
    onLoad: function (options) {
        let arr = [
            {
                "name": "12345678989"
            },
            {
                "name": "hhh"
            },
            {
                "name": "地这究图选由"
            },
            {
                "name": "42245678989"
            },
            {
                "name": "支高动经可接"
            },
            {
                "name": "www"
            },
            {
                "name": "革百看回压采"
            },
            {
                "name": "然场干总每起"
            },
            {
                "name": "d切"
            },
            {
                "name": "知再议速看青"
            },
            {
                "name": "哈哈"
            },
            {
                "name": "术着白治志接"
            },
            {
                "name": "斗用重从水品"
            },
            {
                "name": "入治说约开图"
            },
            {
                "name": "道与需走应任"
            },
            {
                "name": "程中标以县林"
            },
            {
                "name": "器者红北门正"
            },
            {
                "name": "准果素造展内"
            },
            {
                "name": "区线志反从说"
            },
            {
                "name": "见题通般行越"
            },
            {
                "name": "间此代之委准"
            },
            {
                "name": "用何极段织林"
            },
            {
                "name": "阶都实快极共"
            },
            {
                "name": "都京米应今下"
            },
            {
                "name": "开车也观车算"
            },
            {
                "name": "已入金本无划"
            },
            {
                "name": "压取它应便关"
            },
            {
                "name": "当无农快品导"
            },
            {
                "name": "起公维业等民"
            },
            {
                "name": "命素府利华新"
            },
            {
                "name": "教想适治器该"
            },
            {
                "name": "查需国价政增"
            },
            {
                "name": "管起来西毛般"
            },
            {
                "name": "广资接最更千"
            },
            {
                "name": "来命确两界地"
            },
            {
                "name": "政团铁层状很"
            },
            {
                "name": "长西信两效加"
            },
            {
                "name": "般则就级好示"
            },
            {
                "name": "方际出产党满"
            },
            {
                "name": "思革青许龙所"
            },
            {
                "name": "从加月引成支"
            },
            {
                "name": "立此验解包众"
            },
            {
                "name": "受器整广速物"
            },
            {
                "name": "已记却界六明"
            },
            {
                "name": "么所指往通情"
            },
            {
                "name": "型界新习此满"
            },
            {
                "name": "争算原究感府"
            },
            {
                "name": "求米当标得任"
            },
            {
                "name": "西响所酸即和"
            },
            {
                "name": "最具展小量目"
            },
            {
                "name": "类再复际方也"
            },
            {
                "name": "到手了议常入"
            }
        ];
        this.setData({
            list: this.pySegSort(arr, "name"),
        })
    }
});
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-03 16:03:16  更:2022-03-03 16:04:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 8:32:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码