1. 程式人生 > >微信小程式 實現城市名稱拼音搜尋框 漢字/拼音(城市區縣定位模組)

微信小程式 實現城市名稱拼音搜尋框 漢字/拼音(城市區縣定位模組)

~ 文末展示專案更新哦 ~

要實現的效果展示如下
拼音搜尋城市名稱效果展示全拼簡拼

總體思路:

  • 首先,資料中,城市物件裡,包含其全拼、簡拼的屬性;
  • 然後,邏輯層,找出 能與 輸入框輸入的字串 相匹配的 物件;
  • 最後,展示層,把所有匹配的城市名都渲染出來。

接下來,我們按步驟來一窺究竟。

首先,是資料

為了舉例方便,test.js 中,我們使用簡化版的資料:

'use strict’
const cityList = [{ "id": "35", "provincecode": "150000", "city": "\u963f\u62c9\u5584\u76df", "code": "152900", "initial"
: "A" ,"short": "alashan", "shorter": "als"}, { "id": "38", "provincecode": "210000", "city": "\u978d\u5c71\u5e02", "code": "210300", "initial": "A" ,"short": "anshan", "shorter": "as"}, { "id": "105", "provincecode": "340000", "city": "\u5b89\u5e86\u5e02", "code": "340800", "initial": "A"
,"short": "anqing", "shorter": "aq"}, { "id": "156", "provincecode": "410000", "city": "\u5b89\u9633\u5e02", "code": "410500", "initial": "A" ,"short": "anyang", "shorter": "ay”}] let finalCityList = []; //用來儲存篩選後的結果

其中,cityList是我們的原始資料,它是一個數組,陣列元素是以A為拼音首字母的4個城市物件:阿拉善盟、鞍山、安慶、安陽。

目前對我們有用的屬性是:

  • short 儲存了城市名的拼音
  • shorter 儲存了城市名的簡拼
  • city 儲存了城市名

接著,是邏輯層:

function auto() {
  let inputSd = “Ay” 
  let sd = inputSd.toLowerCase();
  let num = sd.length
  let temp = cityList.filter(
                item => {
                  let test = item.short.slice(0,num)
                  return (test && test == sd)
                }
              );
  let tempShorter = cityList.filter(
                itemShorter => {
                  let testShorter = itemShorter.shorter.slice(0,num)
                  return (testShorter && testShorter == sd)
                }
              )

 if(temp[0]) {    //全拼匹配
   console.log("temp");
   console.log(temp);
 }else if(tempShorter[0]) {  //簡拼匹配
   console.log("tempShorter");
   console.log(tempShorter);
 }else {
   return
 }
}

我們假設輸入框輸入的值是 “Ay”

考慮到使用者可能輸入大寫,也可能輸入小寫,我們用toLowerCase()來排除這種干擾。

接下來,就要用輸入的字串和城市名的拼音做匹配。

要做匹配,那麼兩邊字串的長度必須是相同的。我們用變數num來儲存輸入字串的長度,然後去城市名的全拼、簡拼字串分別擷取相同長度的子串。

擷取這一步用到了filter( )。它接收一個引數,這個引數是一個函式,返回一個布林值。filter()把傳入的函式依次作用於每個元素,然後根據返回值是true還是false決定保留還是丟棄該元素。

我們看作為引數的函式:

    item => {
                let test = item.short.slice(0,num)    
                return (test && test == sd)
            }

對陣列中的每一個元素執行這個箭頭函式。對該元素的short屬性,用slice()切一個子串。如果該子串和存在,並且和輸入的字串相等,則返回。相當於

      item => {
                let test = item.short.slice(0,num)
                   if(test && test == sd){
                   return item
                    }
              }

返回值轉為truefalsefilter( )據此得到全拼中,能和輸入字串相匹配的新陣列。賦給臨時陣列temp
同理,得到簡拼中相匹配的臨時陣列tempShorter

此時,執行該檔案

node test.js

得到篩選出的匹配城市的陣列:和”Ay”相匹配的是簡拼,安陽市

tempShorter
[ { id: '156',
    provincecode: '410000',
    city: '安陽市',
    code: '410500',
    initial: 'A',
    short: 'anyang',
    shorter: 'ay' } ]

如果把假設的輸入值從“Ay”改為”A”,執行,得到結果:所以4個城市的全拼都匹配

temp
[ { id: '35',
    provincecode: '150000',
    city: '阿拉善盟',
    code: '152900',
    initial: 'A',
    short: 'alashan',
    shorter: 'als' },
  { id: '38',
    provincecode: '210000',
    city: '鞍山市',
    code: '210300',
    initial: 'A',
    short: 'anshan',
    shorter: 'as' },
  { id: '105',
    provincecode: '340000',
    city: '安慶市',
    code: '340800',
    initial: 'A',
    short: 'anqing',
    shorter: 'aq' },
  { id: '156',
    provincecode: '410000',
    city: '安陽市',
    code: '410500',
    initial: 'A',
    short: 'anyang',
    shorter: 'ay' } ]

到此,我們已經實現了對城市的篩選。

因為,在成功地將匹配的城市名渲染出來以後,我們還需要對列表中的專案進行一系列操作,比如點選其中的某個城市,得到其城市名、城市代號等等資訊,所以,直接簡單地用類似[“A市”,“B市”,“C市”,“D市”]的方法渲染出來是不夠的。
我們還需要用物件的形式來展現。

test.js中,做如下修改:

在分別就全拼,簡拼做完篩選後,如果臨時陣列temp(或tempShorter,下同)存在,則用map( ),對陣列中的每個元素進行這樣的操作:

構建臨時物件tempObj,包含兩個屬性,分別是城市名稱 和 城市程式碼。
然後,將這個物件push( )finalCityList陣列中。在這個結果陣列中,包含了我們之後操作所需要的資訊。

test.js

… … 

 if(temp[0]) {
   console.log("temp");
   temp.map(
     item => {
       let tempObj = {};
       tempObj.city = item.city
       tempObj.code = item.code
       finalCityList.push(tempObj)
     }
   )
 }else if(tempShorter[0]) {
   console.log("tempShorter");
   tempShorter.map(
     item => {
       let tempObj = {};
       tempObj.city = item.city
       tempObj.code = item.code
       finalCityList.push(tempObj)
     }
   );
 }else {
   return
 }
}
auto();
console.log(finalCityList);

此時,執行該檔案

node test.js

得到結果:符合“A”的全拼

temp
[ { city: '阿拉善盟', code: '152900' },
  { city: '鞍山市', code: '210300' },
  { city: '安慶市', code: '340800' },
  { city: '安陽市', code: '410500' } ]

接下來,我們考慮

展示層 中渲染

渲染邏輯層得到的結果

我們很自然地想到了小程式中的列表渲染

cityselector.wxml

<view class="input">
<input bindinput="bindKeyInput" placeholder="輸入城市名或拼音查詢" placeholder-style="font-size: 30rpx" value="{{inputName}}"></input>
</view>


<ul wx:for="{{completeList}}" wx:key="index" class="ul">
  <li bindtap="bindCity" data-city="{{item.city}}" data-code="{{item.code}}" class="li">{{item.city}}</li>
</ul>

相對應的
cityselector.js

Page({
  data: {
    cityList: [這個陣列儲存城市物件的原始資料], 
    inputName: ‘’,   //實時儲存input輸入的字串
    completeList: [], //儲存篩選之後匹配的城市物件
    ...
  },

  … … 


  bindKeyInput: function(e) {
    console.log(e.detail.value);
    this.setData({
      inputName: e.detail.value
    })
    this.auto()
  },

  //自動匹配的函式
  auto: function() {
    let inputSd = this.data.inputName //目前輸入框內的資訊
    let sd = inputSd.toLowerCase(); //大小寫
    let num = sd.length
    const cityList = this.data.cityList;
    let finalCityList = []
    let temp = cityList.filter(
                  item => {
                    let text = item.short.slice(0,num)
                    return (text && text == sd)
                  }
                );
    let tempShorter = cityList.filter(
                  itemShorter => {
                    let textShorter = itemShorter.shorter.slice(0,num)
                    return (textShorter && textShorter == sd)
                  }
                )

   if(temp[0]) {
     temp.map(
       item => {
         let testObj = {};
         testObj.city = item.city
         testObj.code = item.code
         finalCityList.push(testObj)
       }
     )
     this.setData({
       completeList: finalCityList,
     })

   }else if(tempShorter[0]) {
     tempShorter.map(
       item => {
         let testObj = {};
         testObj.city = item.city
         testObj.code = item.code
         finalCityList.push(testObj)
       }
     );
     this.setData({
       completeList: finalCityList,
     })

   }else {
     return
   }
 },
})

以上,基本手動完成了微信小程式的 城市名稱拼音搜尋框

還需注意,

  • cityselector.wxml 中通過 data-*的方式,將相關資料傳入,之後才能通過點選事件,在dataset中取到。
  • <input>輸入框可以再通過繫結下面這個 失焦觸發 的方法,實現 輸入框中字串的及時清空

    bindBlur: function(e) {
    console.log("bindBlur");
    this.setData({
      inputName: ''
    })
    },
    
  • 加個漂亮的樣式

相關專案:

案例展示

功能更新

與拼音搜尋同理,添加了漢字搜尋
程式碼詳見專案。

專案更新:

專案更新展示

更新說明:

原功能

  • 自動定位 城市、區縣(也支援手動重新定位)
  • 手動 漢字、拼音搜尋 城市
  • 亦可通過 側邊欄 選擇,城市按拼音首字母排列
  • 選擇好城市後,自動顯示 轄下區縣

更新內容

  • 實現了首頁與城市選擇頁面之間的資料通訊效果
  • 針對真機除錯發現的,輸入漢字時,輸入法行為與開發環境不一致的問題,做了修改優化。
  • 針對定位模組在IOS中,側面字母條的顯示問題,進行了樣式優化
  • 優化了demo樣式
  • 升級了搜尋功能,支援搜尋335個城市(及相應級別地區)。截至目前,最新的國家統計局2016年統計年鑑中,地級市291個,地級行政區劃334個。

注:

在專案中發現簡拼使用率不高,故在搜尋功能的更新中,沒有在城市資料新增簡拼的屬性,但保留了簡拼搜尋的程式碼邏輯。可隨時看情況恢復功能。