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