首页 > 编程 > JavaScript > 正文

vue实现城市列表选择功能

2019-11-19 13:29:26
字体:
来源:转载
供稿:网友

成果展示

最后的成果就是下面所展示的内容,因为gif图没有做,只能截图所展示,接下来,会带着大家一步一步的完成下面功能,脚手架搭建和node安装在本次案例不会讲解,如果了解,可以在我的博客园找到有详细介绍

准备工作:

 引入axios插件,调用better-scroll第三方插件,本地json文件,可以参考目录中的city.json,有条件的也可以自己去扒

功能分析

1.获取json数据展示城市列表 。

2.侧边字母定位滚动到相应的位置。

3.实现搜索城市

接下来我们开始对组件进行划分:本次案例中,总共划分为五个组件,下面就是组件的划分图

创建city组件,通过父组件获取数据,传递给子组件

<template> <div class="city">  <CityHeader></CityHeader> //头部  <Search :list="cities"></Search> //搜索  <List :hot="hotCity" :letter="letter" :list="cities"></List> //城市列表  <Alphabet @chang="handleLetterChang" :list="cities"></Alphabet> //A-Z </div></template><script>import axios from 'axios'import CityHeader from './components/Header'import Search from './components/Search'import List from './components/List'import Alphabet from './components/Alphabet'export default { data () {  return {   cities:{}, // 城市列表   hotCity:[], //热门城市   letter: '' // A-Z  } }, components: {  CityHeader,  Search,  List,  Alphabet }, methods:{  getCityInfo () {   axios.get('/api/city.json').then(this.getCityInfoSucc)  },  getCityInfoSucc(res){    res = res.data   if (res.ret && res.data) {    const data = res.data    this.hotCity = data.hotCities    this.cities = data.cities   }   console.log(this.cities)  },  handleLetterChang(letter) { //接受子组件传过来的//   console.log(letter)   this.letter = letter  } }, mounted () {  this.getCityInfo () }}</script><style scoped lang="stylus"></style>

把得到的数据分次传递个对应的子组件,这样有利于网站优化,不用频繁的请数据

<template> <div class="city">  <CityHeader></CityHeader>  <Search :list="cities"></Search>  <List :hot="hotCity" :letter="letter" :list="cities"></List>  <Alphabet @chang="handleLetterChang" :list="cities"></Alphabet> </div></template>export default { data () {  return {   cities:{}, // 城市列表   hotCity:[], //热门城市   letter: '' // A-Z  } }, components: {  CityHeader,  Search,  List,  Alphabet }, methods:{  getCityInfo () {   axios.get('/api/city.json').then(this.getCityInfoSucc) //请求本地配置的mock数据  },  getCityInfoSucc(res){    res = res.data   if (res.ret && res.data) {    const data = res.data    this.hotCity = data.hotCities    this.cities = data.cities   }  } }, mounted () {  this.getCityInfo () }}

创建头部组件,

<template> <div class="header">  城市选择  <router-link to="/">   <div class="iconfont back-icon"></div>  </router-link> </div></template><script>export default {}</script><style scoped lang="stylus">@import '~styles/varibles.styl';@import '~styles/mixins.styl';.header overflow: hidden height $headerHeight line-height: $headerHeight text-align: center color: #fff background: $bgColor font-size: .4rem .back-icon  position: absolute  left: 0  top: 0  width: .64rem  font-size: .4rem  text-align: center  color: #fff</style>

创建搜索组件页面,接受父组件传递的数据,引入better-scroll第三方插件,实现列表滚动

<template> <div>  <div class="search">   <input v-model="keyword" class="search-input" type="text" placeholder="输入城市名或者拼音" />  </div>  <div class="search-content" ref="search" v-show="keyword">   <ul>    <li class="serach-item border-bottom" v-for="item in listItem" :key="item.id">{{item.name}}</li>    <li v-show="hasNoData" class="serach-item border-bottom">没有搜索到匹配的数据</li>   </ul>  </div> </div></template><script>import BScroll from 'better-scroll'export default { props: {   list: Object, }, data() {  return {   keyword:'',   listItem:[],   timer:null  } }, computed: {  hasNoData() {   return !this.listItem.length //没有搜索的条件是否显示  } }, watch: {  keyword () {   if (this.timer) {    clearTimeout(this.timer)   }   if(!this.keyword) { //清空    this.listItem = ""    return   }   this.timer = setTimeout(() => {    const result = []    for (let i in this.list) {     this.list[i].forEach((value) => { //匹配搜索的条件      if (value.spell.indexOf(this.keyword) > -1 || value.name.indexOf(this.keyword) > -1) {       result.push(value)      }     })    }    this.listItem= result   },100)  } }, mounted () {  this.scroll = new BScroll(this.$refs.search) }}</script><style scoped lang="stylus">@import '~styles/varibles.styl'@import '~styles/mixins.styl'.search height: .72rem padding: 0 .1rem background:$bgColor .search-input  box-sizing: border-box  width:100%  height: .62rem  line-height: .62rem  text-align: center  border-radius: .06rem  padding: 0 .1rem  color: #666.search-content  z-index: 1 overflow:hidden position:absolute top: 1.58rem left: 0 right: 0 bottom: 0 background: #eee .serach-item  line-height: .62rem  padding-left:.2rem  color:#666  background: #fff</style>

创建城市列表组件,引入better-scroll插件,实现列表滚动,通过watch监听letter,实现字母与城市列表滚动

<template> <div class="list" ref="wrapper">  <div>   <div class="area">    <div class="title border-topbottom">当前城市</div>    <div class="button-list">     <div class="button-wrapper">      <div class="button">郑州</div>     </div>    </div>   </div>   <div class="area">    <div class="title border-topbottom">热门城市</div>    <div class="button-list">     <div class="button-wrapper" v-for="item in hot" :key="item.id">      <div class="button">{{item.name}}</div>     </div>    </div>   </div>   <div class="area"     v-for="(item,key) in list"     :ref="key"    :key="key">    <div class="title border-topbottom">{{key}}</div>    <ul class="item-list">     <li class="item border-bottom"       v-for="listInner in item"       :key="listInner.id"     >{{listInner.name}}</li>    </ul>   </div>  </div> </div></template><script>import BScroll from 'better-scroll'export default { props: {   hot: Array,   list: Object,   letter:String  }, mounted () {  this.scroll = new BScroll(this.$refs.wrapper) }, watch:{  letter () { //监听列表滚动事件 A-Z   if(this.letter) {    const element = this.$refs[this.letter][0]    this.scroll.scrollToElement(element)   }  } }}</script><style scoped lang="stylus">@import '~styles/varibles.styl';@import '~styles/mixins.styl';.border-topbottom &:before  background: #ccc &:after  background:#ccc.border-bottom &:before  background: #ccc.list overflow: hidden position:absolute top:1.58rem left:0 right:0 bottom:0 .title  line-height: .54rem;  background: #eee;  padding-left: .2rem;  color: #666;  font-size: .26rem; .button-list  overflow:hidden  padding: .1rem .6rem .1rem .1rem  .button-wrapper   float:left   width:33.33%   .button    margin: .1rem    padding: .1rem 0    text-align: center    border: .02rem solid #ccc    border-radius: .06rem .item-list  .item   line-height: .76rem   color:#212121   padding-left: .2rem   font-size: .28rem   text-overflow: ellipsis   white-space: nowrap</style>

创建字母组件,点击字母,左边列表城市想对应,通过this.$emit事件,子组件在触发的事件传递给父组件,父组件通过子组件传递的事件,在传递给List组件,

<template> <div class="list">  <li class="item"   :ref="item"    @click="handeClick"     @touchstart="handleTouchStart"     @touchmove="handleTouchMove"     @touchend= "handleTouchEnd"    v-for="item of letter"     :key="item">{{item}}</li> </div></template><script>export default { props: {   list: Object }, data () {  return {   touchstart:false,   startY:0,   timer: null  } }, updated () {  this.startY = this.$refs['A'][0].offsetTop }, computed: {  letter () {   const letter =[]   for (let i in this.list) { //循环A-Z    letter.push(i)   }   return letter  } }, methods: {  handeClick(e) {   this.$emit('chang',e.target.innerText) //传给父组件City  },  handleTouchStart () {   // 手指放上   this.touchstart = true  },  handleTouchMove (e) {   // 手指移动   if(this.touchstart) {    if(this.timer) {     clearInterval(this.timer)    }    this.timer = setTimeout(() => {     const touchY = e.touches[0].clientY -79 //到蓝色头部的距离     const index = Math.floor((touchY - this.startY ) / 20)     if(index >=0 && index < this.letter.length) {      this.$emit('chang',this.letter[index])     }    },16)   }  },  handleTouchEnd () {   // 手指离开   this.touchstart = false  } }}</script><style scoped lang="stylus">@import '~styles/varibles.styl';@import '~styles/mixins.styl';.list display: flex flex-direction:column justify-content: center position:absolute top: 1.58rem right: 0 bottom: 0 width: .4rem .item  line-height:.44rem  text-align: center  color: $bgColor  list-style:none</style>

总结

以上所述是小编给大家介绍的vue实现城市列表选择功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对武林网网站的支持!

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表