用vue实现城市选择组件

还是照旧加前提:页面极丑!请忽略,咱们看功能就行,懒得写样式了

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

前提:安装vue-cli vuex axios

目标:
1、实现头部搜索城市功能(v-if判断input不为空时,searchaction搜索城市结果列表块元素为true,indexof查找数据中的关键字)
2、遍历数组找出hot为true的热门城市
3、遍历数据,charAt(0)获取城市名称拼音的首拼字母,转换为大写,去重赋值,A-Z排序。2个用途,1是定义子集,按首拼该字母首拼的城市,2是显示在页面右侧,点击页面滚动到该字母子集的位置
4、点击城市,该城市的id 、name等数据用vuex保存到全局中去供其他组件获取到值

上代码

html部分

<div class="city">
    <header>
      <input type="text" v-model="searchcity" class="input-clear" placeholder="城市/拼音">
       <div class="over" v-if="searchaction">
        <ul>
          <li class="cityte" v-for="(item,index) in searcharr" :key="index" @click="choosecity(item.name,item.id)">{{item.name}}</li>
        </ul>
      </div>
    </header>
    <div class="mui-content">
      <div class="hot-city">
        <p>当前城市:{{this.$store.state.locatecityname}}</p>
        <p style="padding:1rem 0 0 0;">热门城市</p>
        <div class="hot-list">
          <div class="item-box fl" @click="choosecity(item.name,item.id)" v-for="(item,index) in hotcity" :key="index">{{item.name}}</div>
        </div>
      </div>
      <div class="city-main">
        <div class="city-list">
          <ul>
          	<li v-for="(item,index) in citymain" :key="index" class="cityli" :id="item.top">
          		<p class="cityle">{{item.top}}</p>
          		<ul>
                <li v-for="(itemx,index) in item.citylist" :key="index" @click="choosecity(itemx.name,itemx.id)" class="cityte">{{itemx.name}}</li>
          		</ul>
          	</li>
          </ul>
        </div>
        <div class="city-letter">
        	<ul>
        		<li v-for="(item,index) in letter" :key="index" @click="lettercity($event)">{{item}}</li>
        	</ul>
        </div>
        <div class="showletter" v-if='showx'>{{showletter}}</div>
      </div>
    </div>
  </div>

js部分

import axios from 'axios'
	export default {
      name:'city',
	  data() {
			return {
        datalist:[],
        letter:[],  //城市首拼列表
        hotcity:[],  //热门城市列表
        citymain:[],  //首拼+该首拼下城市列表
        showx:false,
        showletter:'',
        searchcity:[],  //输入框输入的文字
        searcharr:[],   //输入查找的城市匹配结果数组
        searchaction:false   //搜索城市结果列表块元素
			}
		},
		
    mounted () {
      axios.get('../../static/city.json').then(response => {
        const citydata = response.data.cities;
        this.datalist = response.data.cities;
        let cityhead = []; //首拼字母集合
        let newcityhead = [];

        for(let i = 0;i < citydata.length;i++){
          let letteritem = citydata[i].pinyin.charAt(0).toUpperCase();  //获取城市拼音的首字母
          cityhead.push(letteritem);

          let ishot = citydata[i];
          if(citydata[i].isHot){
            this.hotcity.push(ishot);
          }
        }
        console.log(this.hotcity)
           
        cityhead = cityhead.sort(function compareFunction(item1,item2) {   //字母按中文顺序排序
          return item1.localeCompare(item2);
        });
        console.log(cityhead);  //字母数组,按中文顺序排,但未去重

        let headarr = [];
        for(let i = 0; i <cityhead.length;i++){   //去重
          if(!headarr.includes(cityhead[i])){
            headarr.push(cityhead[i]);
          }
        } 
        console.log(headarr);
        this.letter = headarr;  //完成去重并赋值

        for(let i = 0;i < headarr.length;i++){
          let cityitem = new Object();  //自定义对象,城市列表下子集(包括首字母、该字母首拼的城市集合)
          cityitem.top = headarr[i];   //首字母
          cityitem.citylist = [];   //该字母首拼的城市集合
             
          for(let j = 0;j < citydata.length;j++){
            if(headarr[i].toLowerCase() === citydata[j].pinyin.charAt(0)){
              let citya = new Object();
              citya.name = citydata[j].name;
              citya.id = citydata[j].cityId;
              cityitem.citylist.push(citya);
            }
          }
          this.citymain.push(cityitem);   
        }
          
      }).catch(error => {
          console.log(error)
          this.errored = true
        }).finally(() => this.loading = false)
      },
    methods:{
      choosecity(name,id) {
        let cityid = id;
        let cityname = name;
        this.$store.commit("updatecityid",cityid)
        this.$store.commit("updatecityname",cityname)
        this.searchaction = false;
      },
      lettercity:function($event){
        let citym = document.getElementsByClassName("city-main")[0];
        let text = $event.currentTarget.innerText;
        let item = document.getElementById(text);
        this.showx = true;
        this.showletter = text;
        let that = this;
        setTimeout(function(){
          that.showx = false;
        },2000);
        citym.scrollTo(0,item.offsetTop - 350);
      }
    },
    watch:{
      searchcity:function(){
        let searchcities = [];
        if(this.searchcity != ""){
          this.searchaction = true;
          for(let i = 0;i < this.datalist.length;i++){
            let str = this.datalist[i].name;
            if(str.indexOf(this.searchcity) != -1){
               let searchcityitem = new Object();
               searchcityitem.id = this.datalist[i].cityId;
               searchcityitem.name = this.datalist[i].name;
               searchcities.push(searchcityitem);
            }  
          }
        }
        this.searcharr = searchcities;
        if(this.searchcity.length == 0){
          this.searchaction = false;  
        }else{
          this.searchaction = true;
        }
      }
    }
	
	}

使用vuex别忘了把它注入到main.js里,我就经常忘/(ㄒoㄒ)/~~
在这里插入图片描述

Vuex 主要有四部分:

state:包含了store中存储的各个状态。
getter: 类似于 Vue 中的计算属性,根据其他 getter 或 state 计算返回值。
mutation: 一组方法,是改变store中状态的执行者,只能是同步操作。
action: 一组方法,其中可以包含异步操作。

刚开始写在man.js里,但后续开发,用的越多越不方便,后来另外创了store目录存放
在这里插入图片描述

actions.js

const actions = {
  ASYNC_SET_NAME({ state, commit, rootState }, payload) {
    setTimeout(() => {
      state.bName = 'asyncName'
    }, 4000)
  }
}

getter.js

const getter = {
  doneTodos:(state,getter) => {
    return state.todos.filter(todo => todo.done)
  }
}

export default getter

index.js

import Vue from 'vue'
import Vuex from 'vuex'
import actions from './actions'
import getter from './getter'
import mutations from './mutations'
import state from './state'


Vue.use(Vuex)


export default new Vuex.Store({
  state,
  getter,
  mutations,
  actions,
})

mutations.js

const mutations = {
  updatecityname(state,arg){
    state.locatecityname = arg
  },
  updatecityid(state,arg){
    state.locatecityid = arg
  },
  savetoken(state,arg){
    state.token = arg;
     sessionStorage.setItem('Author',arg);
  },
}

export default mutations

state.js

const state = {
  locatecityname:'',
  locatecityid:'',
}

export default state

最后,差点忘了,mock的城市数据city.json,当时我随便搜搜就找到了,懒得搜的,直接去我git里面拿吧
https://github.com/czzxff/city

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值