成果展示

最后的成果就是下面所展示的内容,因为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>

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>
</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实现城市列表选择的更多相关文章

  1. [RN] 全国城市列表选择 (包含定位城市、热门城市、全国城市)

    全国城市列表选择 (包含定位城市.热门城市.全国城市) 用ScrollView 实现,解决 SectionList 实现的卡顿问题 实现效果如图: 代码实现如图: 主逻辑文件 cityList.js ...

  2. vue-cli 3.0 实现A-Z字母滑动选择城市列表

    项目地址: https://github.com/caochangkui/vue-cli3 项目代码: 城市列表首页: City.vue <template> <div id=&qu ...

  3. vue 城市列表与字母表联动

    实现两个联动 一是点击右侧字母的时候,城市列表出现相应首字母下的城市 二是鼠标在字母表上滑动的时候,城市列表实时跟着变化 一.点击字母出现相应的列表,给每个字母设置handleLetterClick事 ...

  4. 在DevExpress程序中使用GridView直接录入数据的时候,增加列表选择的功能

    在我上篇随笔<在DevExpress程序中使用Winform分页控件直接录入数据并保存>中介绍了在GridView以及在其封装的分页控件上做数据的直接录入的处理,介绍情况下数据的保存和校验 ...

  5. Vue2.5开发去哪儿网App 城市列表开发之 兄弟组件间联动及列表性能优化

    一,  兄弟组件间联动 1.  点击城市字母,左侧对应显示 给遍历的 字母 添加一个点击事件: Alphabet.vue @click="handleLetterClick" ha ...

  6. vue | 基于vue的城市选择器和搜索城市对应的小区

    城市选择器应该是比较常用的一个组件,用户可以去选择自己的城市,选择城市后返回,又根据自己选择的城市搜索小区. 功能展示 这是选择结果 这是选择城市 这是搜索小区 这是搜索小区接口,key为城市名字,i ...

  7. Android例子源码非第三方实现根据字母排序的城市列表

    values 下dimens.xml <resources> <!-- Default screen margins, per the Android Design guidelin ...

  8. Windows Phone 8.1 新特性 - 控件之列表选择控件

    本篇我们来介绍Windows Phone 8.1 新特性中的列表选择控件. 在Windows Phone 8 时代,大家都会使用 LongListSelector 来实现列表选择控件,对数据进行分组显 ...

  9. iOS开发——UI篇&下拉弹出列表选择项效果

    下拉弹出列表选择项效果 右边菜单中的按键,点击弹出一个列表可选择,选择其中一个,响应相应的事件并把文字显示在右边的菜单上:弹出下拉效果使用LMDropdownView插件,可以用POD进行加载pod  ...

随机推荐

  1. winSockets编程(三)最简单的C/S形式

    功能:向服务器端发送一个字符串,属于最简易的形式,一共需要4个主要步骤,初始化-建立套接字-连接服务器-发送数据 /****************************************** ...

  2. 1033 To Fill or Not to Fill

    PAT A 1033 To Fill or Not to Fill With highways available, driving a car from Hangzhou to any other ...

  3. app.json

    APP.JSON 文件来对微信小程序进行全局配置,决定页面文件的路径.窗口表现.设置网络超时时间.设置多 TAB 等.相当于iOS开发中的AppDelegate 注意该文件不可添加任何注释. {   ...

  4. redis简单使用

    主要参考资料:http://wiki.jikexueyuan.com/project/redis-guide/data-type.html一.redis 安装1.在官网下载安装包2.解压安装包 tar ...

  5. flume遇到的问题

    Caused by: java.lang.IllegalStateException: Unable to add FlumeEventPointer [fileID=, offset=]. Queu ...

  6. cxGrid控件过滤排序和TClientDataSet同步

    https://www.cnblogs.com/false/archive/2013/02/24/2924240.html procedure TReport10Form.cxGridViewData ...

  7. python- 动态加载目录下所有的类

    # 背景 自动化测试框架中model层下有很多类,用来操作mysql的,使用的时候需要把全部的类加载进来,需要使用到动态加载类 # 解决方法 使用pkgutil,内置的方法,常用的话有两个方法 ite ...

  8. kafka各个版本特点介绍和总结

    kafka各个版本特点介绍和总结 1.1 kafka的功能特点: 分布式消息队列 消息队列的数据模型, 形成流式数据. 提供Pub/Sub方式的海量消息处理.以高容错的方式存储海量数据流.保证数据流的 ...

  9. 浅析C#中的Thread ThreadPool Task和async/await

    .net 项目中不可避免地要与线程打交道,目的都是实现异步.并发.从最开始的new Thread()入门,到后来的Task.Run(),如今在使用async/await的时候却有很多疑问. 先来看一段 ...

  10. ElectronNetTest

    系统环境:Ubuntu 18.04.2 Desktop 软件环境:asp.net core 2.2,Node.js(version>8.6) Github上有人说不支持 asp.net core ...