Component({ // 组件的对外属性 properties: { data: { type: Array, value: [], }, // 组件外传递进来的数据 attr: { type: String, value: 'label' }, // 需要进行首字母处理的属性,默认是"label" }, ... })
然后,针对组件外传递进来的数据,做一次转换。
// 静态数据的存储 const Static = { list: [] } Component({ ... methods: { // 初始/重置数据 init () { const { data, attr } = this.properties; let changeData = [], // 转换后的数据 inChangeData = {}; // 存储转换后的数据对应字母的索引值 data.map(v => { // 获取首字母拼音 let firstLetter = this.getFirstLetter(v[attr]); // 循环对比检测 firstLetter.split('').map(str => { if (str in inChangeData) { // 有首字母相同的项, // 则添加入已有的项里面 changeData[inChangeData[str]].list.push(v); } else { // 没有首字母相同的项, // 则在尾部追加一条新的数据, // 储存对应的字母值(firstLetter), // 同时存储该字母对应的索引 changeData.push({ firstLetter: str, list: [v] }); inChangeData[str] = changeData.length - 1; } }); }); // 此时转换后的数组属于乱序, // 需要对乱序的数组进行排序 changeData.sort((pre, next) => pre.firstLetter < next.firstLetter ? -1 : 1); // 若存在“#”项,将位置位移至底部 if (changeData[0].firstLetter === '#') { const firstArr = changeData.splice(0, 1); changeData = [...changeData, ...firstArr]; } // 存储转换后的数据, // this.data.list的数据对应页面的展示数据,因为有搜索功能,数据可能会变更, // 在静态的数据里面,也存储1份数据,方便后续的搜索等功能。 this.setData({ list: changeData }); Static.list = changeData; }, } ... });
初始化函数有了之后呢,当然是调用它啦。
Component({ lifetimes: { // 在组件实例进入页面节点树时执行初始化数据 attached () { this.init(); } }, observers: { // 考虑到组件传递的数据存在变更的可能, // 在数据变更的时候,也要做一次初始化 'data, attr, icon' (data, attr) { this.init(); } }, })
接下来是搜索功能啦~
先给页面搜索框加个监听事件(input)
<view> ... <view> <view> <icon></icon> <input type="text" placeholder="搜索" value="{{ search }}" bindinput="searchData" /> </view> </view> ... </view>
接着是JS的事件
const Static = { list: [] } Component({ ... methods: { searchData (e) { const { value } = e.detail; // 用户输入的值 const { list } = Static; // init存储的静态数据,用来做数据对比 const { attr } = this.properties; // 要对比的属性值 let result = [], tem = {}; // 没有搜索内容,返回全部内容 if (value.length === 0) { this.setData({ list: Static.list }); return; } // 检索搜索内容 list.map(v => { // 获取所有跟value匹配上的数据 const searchList = v.list.filter(v => v[attr].indexOf(value) !== -1); if (searchList.length > 0) { // 此处原理类似楼上init的对比,此处不细说, // 反正我懒我有理(0.0) if (v.firstLetter in tem) { const _list = result[tem[v.firstLetter]].lish; result[tem[v.firstLetter]].lish = [..._list, ...searchList]; } else { result.push({ firstLetter: v.firstLetter, list: [...searchList] }); tem[v.firstLetter] = result.length - 1; } } }); // 存储数据 this.setData({ list: result, search: value }); } }, ... });
侧边栏字母导航
(突然觉得,写文好累啊!!!)
写这块的时候呢,楼主发现了iPhone通讯录侧边导航栏有个问题, 手指在字母导航栏上滑动的时候,有时候很难确认自己滑到了哪个区域?!
然鹅这个问题呢,楼主发现了微信的通讯录,针对这块添加了手指滑动的时候,添加了个结构来帮助用户确认目前所处的区域。
楼主本着学习的精神,借(chao)鉴(xi)了这个效果,来个效果图。
贴一下新的wxml结构
<!-- 侧边导航 --> <view catchtouchstart="subTouchStart" catchtouchmove="subTouchMove" catchtouchend="subTouchEnd"> <view wx:for="{{ list }}" data-firstLetter="{{ item.firstLetter }}" wx:key="firstLetter"> {{ item.firstLetter }} <!-- 以下这块就是新增的结构啦 S --> <view data-desc="{{ item.firstLetter }}" ></view> <!-- 以上这块就是新增的结构啦 E --> </view> </view>