前言
在不久的将来我无事可做。如果我觉得自己很闲,我宁愿为自己做点什么。敢想敢做,所以我选择了为微信小程序做一个模仿iPhone通讯录效果的定制组件。
让我们看看需要实现的核心功能。
按照第一个单词的第一个字母排序;实现输入搜索功能;侧边栏字母导航;
基本分为3个区块:
顶部的搜索区域;内容的显示区域;侧字母导航栏区域;//index.wxmlview类='main!-顶部搜索区域-view class=' header'/view!-内容区-滚动-查看类='滚动'/滚动-查看!-侧面导航-视图类别=' sub _ nav '/视图/视图[顶部搜索区域]
你可以一目了然地直接粘贴代码。
View class='header' /这里有些人可能会问,为什么不使用小程序的标签组件。_?//原因是.我不需要,你还能咬我?(oo)//哈哈哈哈~开玩笑,其实小程序的标签组件还不支持输入!View class=' label '图标/图标输入类型=' text '占位符=' search '/view/view[内容显示区域]
说一眼就要挨打?joy:
根据图片可以看出有两个区域。
红色边框包围的外框负责划定展示范围;绿色方框包围的区域包含字母标题和相应的子项。代码如下:
scroll-view class=' scroll ' view class=' dl ' view class=' dt '下面是字母标题。/view view class='dd' span当然,这是展览的内容。/span/view/view/scroll-view[侧字母导航栏区域]
为了节省文章的篇幅,这里没有映射,很简单,只是并排。
view class=' sub _ nav ' view class=' option '这里是输出字母。/view/view,接下来是wxss的样式。
考虑到wxss的风格很多,我就直接贴代码链接了。感兴趣的童鞋可以看看。
之后,是时候贴一张效果图了。(不要吐丑,宝宝会不开心的!pensive:)
结构样式完成后,粘贴自定义构件的基本文件
//index . JSON { ' component ' : true }//index . js component({ properties : }、//组件的外部属性data3360 {}、//组件的内部数据lifetimes3360 { }、//life life methods : { }//event })现在功能正常了!
按第一个单词的第一个字母排序
说实话,我对实现这个功能毫无头绪,这时候就不得不求助于伟大的“度娘/谷歌”了。
楼主“搜了一下网络”后,他找到了以下页面的源代码参考:
因为楼主的问题,网站被遗忘了。如果有你认识的童鞋,贴个链接告诉楼主,楼主会很快添加。源代码的原理大致描述如下:
包含20902个汉字和375个多音字的Unicode编码,然后用JS切割声母,转换成Unicode进行比较,最后返回声母对应的拼音。
//对应于汉字的Unicode编码文件//ommultidiff=多音字| firstLetterMap=汉字导入first store from’。/first Chinese letter ';//获取初始拼音函数get first letter(val){ const first val=val。charat(0);If (/)。*[ U4E 00- U9F 5]。*/.test(first val)){//处理汉字//将其转换为Unicode编码,与firstStore中的数据进行比较,然后返回对应的参数Const Code=Firstval。charcodeat(0);//在firststore.omultidiff中转换为Unicode代码返回代码?first store . omultidiff[代码]: first store . first lettermap . charat(代码-19968);} else {//这里处理非中国人。//检查是否是字母,如果是,直接返回大写字母。//如果不是,返回“#”/[a-za-z]$/。测试(第一次val)?first val . touppercase(): ' # ';} }}getFirstLetter('东城区');//输出结果:DfirstChineseLetter.js地址
在获得首字母的方法之后,是时候处理数据了。
首先,定义组件所需的参数。
组件({ //组件的外部属性属性: {data: {type3360array,value: [],},//从组件外部传入的数据attr 3360 { type 3360 string,Value: 'label' },//需要初始化的属性是' label' },}默认情况下。)然后,对从组件外部传入的数据进行转换。
//静态数据的存储const static={list: []}组件({ 0.methods : {//init/reset data init(){ const { data,attr }=this.properties让changeData=[],//转换后的数据在changeData={ };//存储索引值data .对应转换数据的字母的map(v={//获取首字母let首字母=this . getfirst letter(v[attr]);//循环对比度检测firstletter.split(')。map(str={ if(in changedata中的str){//有一个项目具有相同的首字母,//然后将其添加到现有项目中,changedata [inchangedata [str]]。list . push(v);} else {//如果没有首字母相同的项,//在末尾添加一个新的数据,//存储对应的字母值(firstLetter),//并存储该字母对应的index changedata . push({ first letter : str,list :[v]};in changedata[str]=changedata . length-1;} });});//此时,转换后的数组出现故障。//无序数组需要排序。changedata.sort ((pre,next)=pre。下一个第一个字母。第一个字母?-1 : 1);//如果有“#”项,将位置移到底部if (changedata [0])。first letter==' # '){ const first star=change data。split (0,1);changeData=[.更改数据,first arr];}//存储转换后的数据。//this . data . list中的数据对应页面的显示数据,因为有搜索功能,数据可能会发生变化。//在静态数据中,还存储了一个数据,方便后续的查找等功能。this . setdata({ list : changeData });Static.list=changeData}, } .});初始化函数可用后,当然会调用它。
当组件实例进入页面节点树时,组件({ lifetime : {//执行初始化数据附加(){ this . init();} },observer RS : {//考虑到组件传递的数据可能发生变化,//当数据发生变化时,初始化' data,attr,icon' (data,attr) {this。init();}},})接下来是搜索功能~
首先,向页面搜索框添加输入
视图类=“main”.view class=' header ' view class=' label ' icon/icon put type=' text ' placeholder=' search ' value=' { { search } } ' bind input=' search data '/view/view./view后跟JS事件
const Static={ list :[]}组件({ 0.methods : { search data(e){ const { value }=e . detail;//用户输入值const { list }=Staticinit中存储的静态数据用于数据比较。const { attr }=this.properties//要比较的属性值为let result=[],tem={ };//无搜索内容,返回所有内容if(值。length===0) {this。setdata ({list: static。list });返回;}//检索搜索内容列表. map(v={//获取所有匹配项的数据,值为const search list=v . list . filter(v=v[attr])。(值)的索引!==-1);If (searchList.length 0) {//这里的原理类似于楼上init的比较,这里就不细说了。//反正我是懒理性(0.0)if(v . tem中第一个字母){const _ list=result [tem [v .第一个字母]]。英语;结果[tem[v.firstLetter]]。丽斯=[._列表,search list];} else { result . push({ first letter :v . first letter,list: [.search list]});tem[v . First Letter]=result . length-1;} } });//存储数据this.setdata ({list:result,search : value });} },});侧边栏字母导航
(突然觉得写作好累!)
写这篇文章的时候,楼主在iPhone通讯录侧面的导航栏发现了一个问题。当手指在字母导航栏上滑动时,有时很难确认他滑入了哪个区域。
不过,至于鹅的问题,楼主找到了微信的通讯录,加了一个结构,帮助用户在为这一块滑动手指时确认当前区域。
本着学习的精神,楼主借用(嘲)和认定(xi)这种效果,并做了效果图。
粘贴新的wxml结构
!-侧面导航-view class=' sub _ nav ' id=' sub nav ' catch touch start=' sub touch start ' catch touch move=' sub touch move ' catch touch end=' sub touch end ' view class=' optio n ' wx : for=' { { list } } ' data-first letter=' { { item . first letter } } ' wx : key=' first letter ' { item . first letter } }!-以下是新添加的结构-s-view class=' max {{item。' first letter===scrollintoview subnav提示'show ' : ' ' } } ' data-desc=' { { item . first letter } } '/view!-上面的是一个新的结构。e-/view/view const static={ list :[],timer: null}组件({ 0.data: {scrollintoview3360 ' ',//标记subnavhint : false当前在哪个字母中,//控制(xi)微信效果的元素},methods : { subtouchstart(){ this。setdata ({subnavhint 3360 true,scrollintoview 3360 ' ' });},subTouchEnd(){ this . setdata({ subnavthint : false });},subTouchMove (e) {//获取constquery=this的值。对应于字母导航栏元素的createselectorquery();query.select('#subNav ')。boundingClientRect();query.selectViewport()。scrollOffset();query . exec(RES={ const { ClientY }=e . touchs[0];//y轴的位置const DomTop=res[0]。顶部;//顶部const {list}中导航元素的位置=this.data//计算指数。//可能这里有人会好奇为什么要除以20。//因为我在样式里写的高度是20px,所以每个字母的面积都是20px。让index=math . round((clientY-DomTop)/20);index=index=list.length?list.length - 1 :索引;//限制索引大于0索引=索引0?0 :指数;//将索引限制在0以内//如果(list[index])限制结果的重复赋值。第一个字母!==this . data . scrollintoview){ this . setdata({ scrollintoview : list[index]。first Letter });//添加一个抖动效果wx .颤音sort();} });} }, } .});结论
文章写到这里,基本上核心功能都实现了~ :卡住_伸出_舌头_闭上_眼睛:(终于写完了.)
通过组件本身的包装,楼主收获了很多!
当然,这个组件还有很多需要改进的地方。如果你对童鞋感兴趣,可以提出你的优化建议。如果楼主有时(兴)或(屈),他会不断改进。
最后再来推一下这个组件,希望能对有需要的童鞋有所帮助。
Github地址
以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。