VUE開發(fā)一個(gè)組件——Vue PC城市選擇

前言

前面用vue開發(fā)了三四個(gè)組件了,都是H5的,現(xiàn)在來(lái)看看PC是如何玩轉(zhuǎn)組件的?其實(shí)和H5相同,樣式不同而已。

VUE開發(fā)一個(gè)組件——Vue PC城市選擇

相關(guān)推薦

《VUE開發(fā)一個(gè)組件——日歷選擇控件》
《VUE開發(fā)一個(gè)組件——移動(dòng)端彈出層(IOS版)》
《VUE開發(fā)一個(gè)組件——Vue tree樹形結(jié)構(gòu)》

都提供源碼,可以去github上面獲取。

城市控件

開始今天的課題,制作一個(gè)PC版的城市選擇控件。

樣式制作

<template>
  <div id="app">
    <p>{{title}}</p>
    <div class="city">
      <input type="text" placeholder="出發(fā)城市" @focus="showCityDialog" @blur="hideCityDialog">
      <div class="city-components" v-if="showCity">
        城市控件
      </div>
    </div>
  </div>
</template>

通過(guò)focus獲取焦點(diǎn)事件,控制組件的顯示,blur失去焦點(diǎn)事件,控制組件的隱藏

export default {
  name: 'app',
  data () {
    return {
      title: 'web秀 - VUE開發(fā)一個(gè)組件——Vue PC城市選擇',
      showCity: false
    }
  },
  methods: {
    hideCityDialog(){
      this.showCity = false;
    },
    showCityDialog(){
      this.showCity = true;
    }
  }
}

css布局,外層用相對(duì)位置,里層用絕對(duì)位置,讓城市組件.city-components跟著input的位置,這里用box-shadow來(lái)凸顯組件。

.city{
  position:relative;
  .city-components{
    position: absolute;
    width: 400px;
    height: 200px;
    box-shadow: 0 0 4px 0 rgba(117,117,117,0.5);
    border-radius: 2px;
    padding: 20px 21px;
  }
}

初步效果


VUE開發(fā)一個(gè)組件——Vue PC城市選擇

數(shù)據(jù)部分

[
  {
    "airportCode": "PEK",
    "cityInfo": "BJ-北京-PEK",
    "cityName": "北京",
    "airportName": "首都",
    "status": 1,
    "lat": 40.0881944004,
    "lng": 116.6033998315
  },
  {
    "airportCode": "YIE",
    "cityInfo": "AES-阿爾山-YIE",
    "cityName": "阿爾山市",
    "airportName": "伊爾施",
    "status": 0,
    "lat": 47.3155940318,
    "lng": 119.9293992017
  },
  {
    "airportCode": "AKU",
    "cityInfo": "AKS-阿克蘇-AKU",
    "cityName": "阿克蘇地區(qū)",
    "airportName": "阿克蘇",
    "status": 0,
    "lat": 41.2657516858,
    "lng": 80.3049157658
  },
  {
    "airportCode": "NGQ",
    "cityInfo": "AL-阿里-NGQ",
    "cityName": "阿里地區(qū)",
    "airportName": "昆莎",
    "status": 0,
    "lat": 32.1081287447,
    "lng": 80.0637591367
  },
  {
    "airportCode": "ALA",
    "cityInfo": "ALMT-阿爾瑪塔-ALA",
    "cityName": "阿拉木圖",
    "airportName": "阿爾瑪塔",
    "status": 0
  },
  {
    "airportCode": "RHT",
    "cityInfo": "ALSYQ-阿拉善右旗-RHT",
    "cityName": "阿拉善右旗",
    "airportName": "阿拉善右旗",
    "status": 0,
    "lat": 39.2338594871,
    "lng": 101.449757309
  },
  {
    "airportCode": "YIW",
    "cityInfo": "YW-義烏-YIW",
    "cityName": "義烏市",
    "airportName": "義烏",
    "status": 0,
    "lat": 29.3464578386,
    "lng": 120.0389750211
  },
  {
    "airportCode": "ZQZ",
    "cityInfo": "ZJK-張家口-ZQZ",
    "cityName": "張家口",
    "airportName": "張家口",
    "status": 0,
    "lat": 40.7461174707,
    "lng": 114.9436254875
  },
  {
    "airportCode": "HSN",
    "cityInfo": "ZS-舟山-HSN",
    "cityName": "舟山",
    "airportName": "普陀山",
    "status": 0,
    "lat": 29.9396135515,
    "lng": 122.3683649114
  },
  {
    "airportCode": "CGO",
    "cityInfo": "ZZ-鄭州-CGO",
    "cityName": "鄭州",
    "airportName": "新鄭",
    "status": 1,
    "lat": 34.5308189222,
    "lng": 113.8526878594
  }
  ...
]

這里只有部分?jǐn)?shù)據(jù),主要是給大家看看結(jié)構(gòu),數(shù)組里面包含對(duì)象,對(duì)象包含多個(gè)字段,下面我們將用airportCode字段的首字母來(lái)分組,排序等。

相關(guān)推薦《js數(shù)據(jù)如何分組排序?》

分組

這里的this.dataList就是數(shù)據(jù)源

let map = {}; // 處理過(guò)后的數(shù)據(jù)對(duì)象
let temps = []; // 臨時(shí)變量
this.dataList.map(item=>{
  if(item.airportCode){
      let ekey = item.airportCode.charAt(0).toUpperCase(); // 根據(jù)key值的第一個(gè)字母分組,并且轉(zhuǎn)換成大寫
      temps = map[ekey] || []; // 如果map里面有這個(gè)key了,就取,沒(méi)有就是空數(shù)組
      temps.push({
          airportCode: item.airportCode,
          airportName: item.cityName
      });
      map[ekey] = temps;
  }
})
console.log(map);

打印map值

VUE開發(fā)一個(gè)組件——Vue PC城市選擇

可以看到已經(jīng)分組成功,但是這樣的數(shù)據(jù)結(jié)構(gòu)在頁(yè)面遍歷不好處理,我們進(jìn)一步處理數(shù)據(jù)

格式化

這里的map就是上面得出的結(jié)果

let list = [];
for(let gkey in map) {
  list.push({
      ckey: gkey,
      cityList: map[gkey]
  })
}

list = list.sort((li1, li2)=> li1.ckey.charCodeAt(0) - li2.ckey.charCodeAt(0));
console.log(list);
VUE開發(fā)一個(gè)組件——Vue PC城市選擇

處理后的數(shù)據(jù)是不是看起來(lái)更容易理解了?數(shù)組包含23的對(duì)象,A-Z(中間個(gè)別沒(méi)有),對(duì)象兩個(gè)字段,一個(gè)是首字母key,另外一個(gè)對(duì)象cityList是數(shù)組,包含A(Z)的所有機(jī)場(chǎng)城市。

這時(shí)候的結(jié)果是不是我們想要的了?請(qǐng)看第一張圖,好像是每4個(gè)字母一組,同時(shí)我們把分組的key也用一個(gè)數(shù)組存起來(lái),這時(shí)候還得重新分組。

let chunk = 4;
let result =[];
for (var i = 0, j = list.length; i < j; i += chunk) {
  result.push(list.slice(i, i + chunk));
}
console.log(result);

let cityListKey = [];
result.map(item=>{
  let ckeys  = '';
  item.map(ritem=>{
      ckeys += ritem.ckey;
  })
  cityListKey.push(ckeys);
})
console.log(cityListKey);
VUE開發(fā)一個(gè)組件——Vue PC城市選擇

終于數(shù)據(jù)是我們要的了,這時(shí)候直接將數(shù)據(jù)渲染到頁(yè)面即可。(當(dāng)然如果后臺(tái)能直接給你這樣的數(shù)據(jù)結(jié)構(gòu),你就感覺(jué)感謝吧)

數(shù)據(jù)渲染

<div class="city-components" v-if="showCity">
    <ul class="filter-tabar clearfix">
        <li v-for="(item,index) in cityListKey" :class="{active:upCityListIndex==index}" @mouseover="upCityListKey(index)">{{item}}</li>
    </ul>
</div>

先把cityListKey渲染出來(lái),并添加樣式

.clearfix{
  &:after{
    content: '';
    display: block;
    clear: both;
  }
}
li{
  list-style: none;
}
ul{
  padding: 0;
  margin: 0;
}
.filter-tabar{
  border-bottom: 1px solid #d7d7d7;
  cursor: pointer;
  li{
    text-align: center;
    padding: 0 14px;
    float: left;
    padding-bottom: 14px;
    font-size: 14px;
    margin: 0 8px;
    margin-bottom: -1px;
    position: relative;
    &.active{
      border-bottom: 1px solid #ff7362;
    }
  }
}
VUE開發(fā)一個(gè)組件——Vue PC城市選擇

Ok,繼續(xù)把下面的數(shù)據(jù)渲染,這時(shí)候就需要事件處理,手勢(shì)滑動(dòng)到哪里,就展示那塊的數(shù)據(jù)(比如鼠標(biāo)知道EFGH,這時(shí)候就只能展示EFGH字母開頭的數(shù)據(jù))。前面做了那么多工作,這里就很好解決了,這里的cityListKey本身就是從分好組的數(shù)據(jù)里面提取的,所以知道下標(biāo)就可以得到想要的數(shù)據(jù)了。

VUE開發(fā)一個(gè)組件——Vue PC城市選擇

所以upCityListKey方法傳入index下標(biāo)。來(lái)取對(duì)應(yīng)數(shù)據(jù)。

upCityListKey(index){
    this.upCityListIndex = index;
    this.upCityList = this.cityList[index];
}

這里用upCityListIndex存入下標(biāo),用來(lái)添加鼠標(biāo)劃入的高亮樣式,用upCityList存需要展示的城市數(shù)據(jù)。然后將upCityList渲染到頁(yè)面

<div class="city-components" v-if="showCity">
    <ul class="filter-tabar clearfix">
        <li v-for="(item,index) in cityListKey" :class="{active:upCityListIndex==index}" @mouseover="upCityListKey(index)">{{item}}</li>
    </ul>
    <div class="city-content">
        <ul v-for="item in upCityList" class="clearfix">
            <label for="">{{item.ckey}}</label>
            <li v-for="ritem in item.cityList" @click="selectDepCity(ritem)">{{ritem.airportName}}</li>
        </ul>
    </div>
</div>
.city-content{
  max-height: 500px;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 10px 13px 0 13px;
  label{
    display: block;
    margin-bottom: 5px !important;
    font-size: 20px !important;
    margin-left: 0 !important;
    color: #5f5f5f !important;
    margin-top: 5px;
  }
  li{
    padding: 6px 0 6px;
    float: left;
    text-align: left;
    font-size: 14px;
    min-width: 56px;
    margin-right: 24px;
    cursor: pointer;
  }
}

同時(shí)去掉..city-componentsheight樣式。

.city-components{
    position: absolute;
    width: 400px;
    // height: 200px;
    box-shadow: 0 0 4px 0 rgba(117,117,117,0.5);
    border-radius: 2px;
    padding: 20px 21px;
}

完成效果

VUE開發(fā)一個(gè)組件——Vue PC城市選擇

源碼地址: vue-c-city

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容