小程序手机通讯录字母导航

微信   2025-01-01 15:02   77   0  

25979_bzik_8663.jpeg

下面pySegSort函数代码中的localeCompare在小程序中似乎不兼容安卓,但是兼容苹果手机,就,挺懵的。

初步解决方案:安装pinyin-pro,地址:pinyin-pro - npm

pinyin(item.name, { pattern: 'first', type: 'array' })[0].toUpperCase()

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

首先是一个函数,这个函数是实现,把中文开头的拼音的首字母提出,比如上面图片里的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组件来实现滑动和字母定位,先粘一下代码:

index.wxml

<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了,下面粘贴一下效果图:

26198_pzwn_9331.png

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

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

index.js

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"),
        })
    }
});


来源:https://blog.csdn.net/qq_43652492/article/details/123231963

博客评论
还没有人评论,赶紧抢个沙发~
发表评论
说明:请文明发言,共建和谐网络,您的个人信息不会被公开显示。