亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

仿iPhone通訊錄制作小程序自定義選擇組件的實現

2019-11-19 11:28:58
字體:
來源:轉載
供稿:網友

前言

近期閑來無事,想著閑著也是閑著,不如給自己搞點事情做!敢想敢做,于是選擇了給微信小程序做個 仿iPhone通訊錄 效果的自定義組件。

先來整理一下,瞧瞧需要實現的核心功能。

  1. 按照第一個字的首字母排序;
  2. 實現輸入搜索功能;
  3. 側邊欄字母導航;

基本上分為3塊:

  1. 頂部的搜索區域;
  2. 內容的展示區域;
  3. 側邊字母導航欄區域;
// index.wxml<view class="main"> <!-- 頂部搜索區域 --> <view class="header"> </view> <!-- 內容區域 --> <scroll-view class="scroll"> </scroll-view> <!-- 側邊導航 --> <view class="sub_nav"> </view></view>

【頂部的搜索區域】

一目了然就直接貼代碼了。

<view class="header"> // 這里或許有人要問,為啥不用小程序的label組件呢。?_? // 原因就是...我就不用,你還能咬我?!^(oo)^ // 哈哈哈哈~開個玩笑,其實是小程序的label組件還沒支持input! <view class="label">   <icon></icon>  <input type="text" placeholder="搜索" /> </view></view>

【內容的展示區域】

再說一目了然會不會被打呢?:joy:

根據圖片就可以看出來,存在2個區域。

  1. 紅框包圍的外框,負責圈定展示的范圍;
  2. 綠框包圍的范圍,包含有字母標題和對應的子項。

代碼如下:

<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.jsComponent({ properties: {}, // 組件的對外屬性 data: {},  // 組件的內部數據 lifetimes: {}, // 生命周期 methods: {}  // 事件});

現在開始實現功能了?。?!

按照第一個字的首字母排序

說實話,實現這塊功能呢,我是沒啥頭緒的,所以這個時候就要求助偉大的“度娘/Google”了。

經過樓主“遍尋網絡”,查找到如下頁面的源碼參考:

因樓主問題,遺忘了該網址,如有知道的童鞋,貼個鏈接告訴下樓主,樓主立馬麻溜的加上。 源碼的原理大概描述下:

收錄 20902 個漢字和 375 個多音字的 Unicode 編碼,然后用JS切割首字母并轉換成 Unicode 進行對比,最后返回對應首字母的拼音。

// 漢字對應的Unicode編碼文件// oMultiDiff = 多音字 | firstLetterMap = 漢字import firstStore from './firstChineseLetter'; // 獲取首字母拼音function getFirstLetter (val) { const firstVal = val.charAt(0); if (/.*[/u4e00-/u9fa5]+.*/.test(firstVal)) { // 處理中文字符 // 轉換成Unicode編碼,與firstStore里面的數據進行對比,然后返回對應的參數 const code = firstVal.charCodeAt(0); // 轉換成Unicode編碼 return code in firstStore.oMultiDiff ? firstStore.oMultiDiff[code] : firstStore.firstLetterMap.charAt(code - 19968); } else { // 這里處理非中文 // 檢測是否字母,如果是就直接返回大寫的字母 // 不是的話,返回“#” return /^[a-zA-Z]+$/.test(firstVal) ? firstVal.toUpperCase() : '#'; }}getFirstLetter('東城區');// 輸出結果:D

firstChineseLetter.js地址

獲取首字母的方法有了之后,就該對數據進行處理了。

首先定義一下組件所需要的參數。

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 class="main"> ... <view class="header"> <view class="label">  <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 }); } }, ...});

側邊欄字母導航

(突然覺得,寫文好累啊?。。。?/p>

寫這塊的時候呢,樓主發現了iPhone通訊錄側邊導航欄有個問題, 手指在字母導航欄上滑動的時候,有時候很難確認自己滑到了哪個區域?!

然鵝這個問題呢,樓主發現了微信的通訊錄,針對這塊添加了手指滑動的時候,添加了個結構來幫助用戶確認目前所處的區域。

樓主本著學習的精神,借(chao)鑒(xi)了這個效果,來個效果圖。

貼一下新的wxml結構

<!-- 側邊導航 --> <view class="sub_nav" id="subNav" catchtouchstart="subTouchStart" catchtouchmove="subTouchMove" catchtouchend="subTouchEnd"> <view class="option" wx:for="{{ list }}" data-firstLetter="{{ item.firstLetter }}" wx:key="firstLetter">  {{ item.firstLetter }}  <!-- 以下這塊就是新增的結構啦 S -->  <view   class="max {{ item.firstLetter === scrollIntoView && subNavHint ? 'show' : '' }}"   data-desc="{{ item.firstLetter }}"  ></view>  <!-- 以上這塊就是新增的結構啦 E --> </view> </view>
const Static = { list: [], timer: null}Component({ ... data: { scrollIntoView: '', // 標記當前處于哪個字母 subNavHint: false, // 控制借(chao)鑒(xi)微信效果的元素 }, methods: { subTouchStart () {  this.setData({ subNavHint: true, scrollIntoView: '' }); }, subTouchEnd () {  this.setData({ subNavHint: false }); }, subTouchMove (e) {  // 獲取字母導航欄元素對應的值  const query = this.createSelectorQuery();  query.select('#subNav').boundingClientRect();  query.selectViewport().scrollOffset();  query.exec(res => {  const { clientY } = e.touches[0]; // Y軸的位置  const DomTop = res[0].top; // 導航元素距離頂部的位置  const { list } = this.data;    // 計算索引,  // 或許看到這里有人會疑問,為什么是除以20?  // 因為樣式里面,我寫的高度是20px,所以每個字母的區域是20px。  let index = Math.round((clientY - DomTop) / 20);   index = index >= list.length ? list.length - 1 : index; // 限制索引大于0  index = index < 0 ? 0 : index; // 限制索引小于0  // 限制結果重復賦值  if (list[index].firstLetter !== this.data.scrollIntoView) {   this.setData({ scrollIntoView: list[index].firstLetter });   // 加個抖動效果   wx.vibrateShort();   }  });  } }, } ...});

結語

文章寫到這呢,基本上核心的功能都已經實現啦~ :stuck_out_tongue_closed_eyes:(終于寫完了...)

通過自己封裝組件,樓主還是有挺大收獲的!

當然,這個組件還有很多可以繼續完善的地方,有興趣的童鞋呢,可以提出你的優化建議,樓主有時(xing)間(qu)的話,會繼續完善下去。

最后,還是推一下這個組件啦,希望它能幫到有需要的童鞋。

github地址

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲社区在线观看| 欧洲精品在线视频| 久久久人成影片一区二区三区观看| 国产91网红主播在线观看| 欧美丰满片xxx777| 97久久精品人人澡人人爽缅北| 国产精品亚洲综合天堂夜夜| 欧美日韩色婷婷| 国产亚洲精品一区二555| 久久综合久中文字幕青草| 欧美激情亚洲综合一区| 欧美成人一区在线| 国产日韩欧美视频在线| 成人观看高清在线观看免费| 亚洲自拍偷拍一区| 一本色道久久综合狠狠躁篇的优点| 91精品视频在线看| 国产精品老牛影院在线观看| 欧美野外猛男的大粗鳮| 大量国产精品视频| 日韩综合中文字幕| 欧美成人精品一区二区| 久久精品国产视频| 欧美电影在线播放| 人人爽久久涩噜噜噜网站| 日韩高清电影免费观看完整版| 日韩欧美在线免费| 国产午夜精品一区二区三区| 日韩小视频在线观看| 欧美性xxxxxx| 亚洲性xxxx| 亚洲免费视频网站| 国产日韩综合一区二区性色av| 欧美日韩高清区| 2019中文字幕在线免费观看| 日韩av在线一区二区| 久久精品成人欧美大片古装| 日韩免费在线电影| 国产日韩中文在线| 国产精品观看在线亚洲人成网| 久久天天躁夜夜躁狠狠躁2022| 亚洲伊人久久大香线蕉av| 国产精品亚洲视频在线观看| 国产欧美精品xxxx另类| 日韩欧美aⅴ综合网站发布| 人妖精品videosex性欧美| 国产欧美精品一区二区三区-老狼| 欧美高清理论片| 国产精品久久久精品| 奇米一区二区三区四区久久| 精品久久久久久久久久| 777午夜精品福利在线观看| 国产日韩精品入口| 最近中文字幕mv在线一区二区三区四区| 在线日韩精品视频| 亚洲欧美日韩一区二区三区在线| 亚洲精品在线看| 中文字幕av一区中文字幕天堂| 亚洲欧美三级伦理| 国产精品久久久久久久app| 亚洲欧美日韩直播| 国产精品男女猛烈高潮激情| 亚洲国产精品久久久久秋霞蜜臀| 九九热99久久久国产盗摄| 欧美亚洲国产成人精品| 国产精品一区二区久久| 久久久久久国产精品三级玉女聊斋| 国产精品自拍偷拍| 久久精品视频va| 亚洲欧美日韩在线一区| 精品亚洲一区二区三区在线播放| 国产婷婷成人久久av免费高清| 亚洲欧洲日本专区| 欧洲s码亚洲m码精品一区| 国产区亚洲区欧美区| 亚洲精品999| 亚洲aⅴ日韩av电影在线观看| 亚洲日韩欧美视频| 亚洲va电影大全| 国产不卡在线观看| 日韩精品免费在线视频观看| 日韩精品视频在线观看免费| 国产视频欧美视频| 欧美性猛交xxxx免费看漫画| 久久精品这里热有精品| www.国产精品一二区| 国产人妖伪娘一区91| 精品国产欧美一区二区三区成人| 日韩动漫免费观看电视剧高清| 久久精品国产v日韩v亚洲| 国产婷婷97碰碰久久人人蜜臀| 日产精品久久久一区二区福利| 97精品国产91久久久久久| 国产婷婷97碰碰久久人人蜜臀| 国产精品一区二区久久| 亚洲天堂男人天堂女人天堂| 欧美精品免费看| 色狠狠久久aa北条麻妃| 亚洲欧美综合精品久久成人| 精品中文字幕在线观看| 久久久久国产精品一区| 亚洲一区二区中文字幕| 国产精品自产拍在线观| 日本一区二区在线免费播放| 不卡av在线网站| 久久精品国产99国产精品澳门| 国产欧亚日韩视频| 国产男女猛烈无遮挡91| 日韩欧美成人精品| 日韩在线www| 国产日本欧美一区二区三区在线| 久久人人爽亚洲精品天堂| 怡红院精品视频| 亚洲人成欧美中文字幕| 欧美午夜视频在线观看| 91精品视频在线免费观看| 亚洲国产成人精品久久| 久久久亚洲成人| 国产成人一区二区三区| 欧美日韩裸体免费视频| 亚洲一区二区三区乱码aⅴ| 国产精品偷伦视频免费观看国产| 久久精品国产电影| 91在线观看免费网站| 国产精品高潮呻吟久久av野狼| 欧美做受高潮1| 成人免费视频a| 奇米四色中文综合久久| 日日噜噜噜夜夜爽亚洲精品| 国产成人91久久精品| 日韩电影中文字幕av| 国产欧美日韩中文| 国产精品久久久久久av福利| 国产最新精品视频| 九九九热精品免费视频观看网站| 国产精品最新在线观看| 精品久久香蕉国产线看观看亚洲| 97**国产露脸精品国产| 亚洲精品第一国产综合精品| 欧美又大粗又爽又黄大片视频| 日韩黄在线观看| 国产精品久久久久久久7电影| 亚洲精品电影网| 久久97精品久久久久久久不卡| 日韩精品亚洲精品| 激情av一区二区| 国产在线精品一区免费香蕉| 中文字幕欧美日韩在线| 裸体女人亚洲精品一区| 欧美日韩中文字幕在线视频| 精品亚洲一区二区三区在线播放| 亚洲精品狠狠操| 日本精品中文字幕| 欧美一区视频在线| 久久高清视频免费| 97高清免费视频| 91国产中文字幕| 日韩av在线免播放器| 国产盗摄xxxx视频xxx69| 日韩成人网免费视频| 欧美激情一级精品国产| 中文字幕日韩有码| 日韩av在线影院| 在线观看欧美视频|