vue实现城市列表选择功能


Posted in Javascript onJuly 16, 2018

成果展示

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

vue实现城市列表选择功能vue实现城市列表选择功能vue实现城市列表选择功能

准备工作:

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

功能分析

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

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

3.实现搜索城市

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

vue实现城市列表选择功能

创建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>

vue实现城市列表选择功能

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

<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实现城市列表选择功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
jQuery 图像裁剪插件Jcrop的简单使用
May 22 Javascript
下拉菜单点击实现连接跳转功能的js代码
May 19 Javascript
jquery 定位input元素的几种方法小结
Jul 28 Javascript
微信jssdk用法汇总
Jul 16 Javascript
jQuery插件EasyUI实现Layout框架页面中弹出窗体到最顶层效果(穿越iframe)
Aug 05 Javascript
bootstrap laydate日期组件使用详解
Jan 04 Javascript
详解vue-loader在项目中是如何配置的
Jun 04 Javascript
javascript中this的用法实践分析
Jul 29 Javascript
vue 重塑数组之修改数组指定index的值操作
Aug 09 Javascript
JavaScript逻辑运算符相关总结
Sep 04 Javascript
vue实现列表垂直无缝滚动
Apr 08 Vue.js
vue本地构建热更新卡顿的问题“75 advanced module optimization”完美解决方案
Aug 05 Vue.js
JavaScript字符串转数字的5种方法及遇到的坑
Jul 16 #Javascript
Angular-UI Bootstrap组件实现警报功能
Jul 16 #Javascript
JS在if中的强制类型转换方式
Jul 15 #Javascript
微信小程序form表单组件示例代码
Jul 15 #Javascript
微信小程序仿朋友圈发布动态功能
Jul 15 #Javascript
Bootstrap Table中的多选框删除功能
Jul 15 #Javascript
详解JavaScript 中 if / if...else...替换方式
Jul 15 #Javascript
You might like
在PHP中执行系统外部命令
2006/10/09 PHP
PHP中如何防止外部恶意提交调用ajax接口
2016/04/11 PHP
PHP环境搭建的详细步骤
2016/06/30 PHP
PHP实现对图片的反色处理功能【测试可用】
2018/02/01 PHP
PHP设计模式之模板方法模式实例浅析
2018/12/20 PHP
Javascript调试工具(下载)
2007/01/09 Javascript
javascript jQuery $.post $.ajax用法
2008/07/09 Javascript
js数组与字符串的相互转换方法
2014/07/09 Javascript
Javascript 拖拽的一些简单的应用(逐行分析代码,让你轻松了拖拽的原理)
2015/01/23 Javascript
JavaScript中用let语句声明作用域的用法讲解
2016/05/20 Javascript
jQuery实现的纵向下拉菜单实例详解【附demo源码下载】
2016/07/09 Javascript
解决canvas画布使用fillRect()时高度出现双倍效果的问题
2017/08/03 Javascript
详解用函数式编程对JavaScript进行断舍离
2017/09/18 Javascript
基于jQuery实现Ajax验证用户名是否可用实例
2018/03/25 jQuery
js Element Traversal规范中的元素遍历方法
2018/04/19 Javascript
微信小程序自定义模态弹窗组件详解
2019/12/24 Javascript
原生js拖拽实现图形伸缩效果
2020/02/10 Javascript
VUE中setTimeout和setInterval自动销毁案例
2020/09/07 Javascript
[01:19:46]DOTA2-DPC中国联赛 正赛 SAG vs DLG BO3 第一场 2月28日
2021/03/11 DOTA
python 实现插入排序算法
2012/06/05 Python
python追加元素到列表的方法
2015/07/28 Python
微信 用脚本查看是否被微信好友删除
2016/10/28 Python
Python SVM(支持向量机)实现方法完整示例
2018/06/19 Python
Pandas中DataFrame的分组/分割/合并的实现
2019/07/16 Python
多版本python的pip 升级后, pip2 pip3 与python版本失配解决方法
2019/09/11 Python
python 检查数据中是否有缺失值,删除缺失值的方式
2019/12/02 Python
ipython jupyter notebook中显示图像和数学公式实例
2020/04/15 Python
骆驼官方商城:CAMEL
2016/11/22 全球购物
小学生环保演讲稿
2014/04/25 职场文书
社会稳定风险评估方案
2014/06/02 职场文书
优秀应届毕业生自荐书
2014/06/29 职场文书
课外活动总结
2015/02/04 职场文书
学校党支部公开承诺书
2015/04/30 职场文书
2019最新校园运动会广播稿!
2019/06/28 职场文书
Python爬虫框架之Scrapy中Spider的用法
2021/06/28 Python
Pygame如何使用精灵和碰撞检测
2021/11/17 Python