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 相关文章推荐
地址栏上的一段语句,改变页面的风格。(教程)
Apr 02 Javascript
Javascript的各种节点操作实例演示代码
Jun 27 Javascript
jQuery的text()方法用法分析
Dec 20 Javascript
浅谈javascript属性onresize
Apr 20 Javascript
Bootstrap模态对话框的简单使用
Apr 29 Javascript
jQuery页面加载初始化的3种方法(推荐)
Jun 02 Javascript
jquery之别踩白块游戏的简单实现
Jul 25 Javascript
javascript中的面向对象
Mar 30 Javascript
JavaScript中splice与slice的区别
May 09 Javascript
layui实现动态和静态分页
Apr 28 Javascript
使用webpack构建应用的方法步骤
Mar 04 Javascript
D3.js(v3)+react 实现带坐标与比例尺的散点图 (V3版本)
May 09 Javascript
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 上一篇,下一篇文章实现代码与原理说明
2010/05/09 PHP
解析php中两种缩放图片的函数,为图片添加水印
2013/06/14 PHP
PHP 安全检测代码片段(分享)
2013/07/05 PHP
PHP的魔术常量__METHOD__简介
2014/07/08 PHP
PHP实现多图片上传类实例
2014/07/26 PHP
php过滤htmlspecialchars() 函数实现把预定义的字符转换为 HTML 实体用法分析
2019/06/25 PHP
一个符号插入器 中用到的js代码
2007/09/04 Javascript
js setTimeout 常见问题小结
2013/08/13 Javascript
js 跳出页面的frameset框架示例介绍
2013/12/23 Javascript
使用nodejs、Python写的一个简易HTTP静态文件服务器
2014/07/18 NodeJs
javascript 常见功能汇总
2015/06/11 Javascript
jQuery动画效果相关方法实例分析
2015/12/31 Javascript
基于Node.js实现nodemailer邮件发送
2016/01/26 Javascript
JS组件Bootstrap按钮组与下拉按钮详解
2016/05/10 Javascript
vue.js实现表格合并示例代码
2016/11/30 Javascript
详解如何在Angular中快速定位DOM元素
2017/05/17 Javascript
JavaScript监听手机物理返回键的两种解决方法
2017/08/14 Javascript
vue-router相关基础知识及工作原理
2018/03/16 Javascript
JS使用遮罩实现点击某区域以外时弹窗的弹出与关闭功能示例
2018/07/31 Javascript
原生JS实现轮播图效果
2018/10/12 Javascript
从0到1搭建Element的后台框架的方法步骤
2019/04/10 Javascript
微信小程序云开发修改云数据库中的数据方法
2019/05/18 Javascript
基于Vue.js与WordPress Rest API构建单页应用详解
2019/09/16 Javascript
Vue是怎么渲染template内的标签内容的
2020/06/05 Javascript
[36:29]2018DOTA2亚洲邀请赛 4.1 小组赛 A组加赛 LGD vs TNC
2018/04/02 DOTA
python分析apache访问日志脚本分享
2015/02/26 Python
在Debian下配置Python+Django+Nginx+uWSGI+MySQL的教程
2015/04/25 Python
Python断言assert的用法代码解析
2018/02/03 Python
如何利用Python动态模拟太阳系运转
2020/09/04 Python
Python监听剪切板实现方法代码实例
2020/11/11 Python
利用python+request通过接口实现人员通行记录上传功能
2021/01/13 Python
介绍一下SQL Server的全文索引
2013/08/15 面试题
工作违纪检讨书
2014/02/17 职场文书
中学生民族团结演讲稿
2014/08/27 职场文书
倡议书作文
2015/01/19 职场文书
JavaScript正则表达式实现注册信息校验功能
2022/05/30 Java/Android