vue实现城市列表选择
成果展示
最后的成果就是下面所展示的内容,因为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实现城市列表选择的更多相关文章
- [RN] 全国城市列表选择 (包含定位城市、热门城市、全国城市)
全国城市列表选择 (包含定位城市.热门城市.全国城市) 用ScrollView 实现,解决 SectionList 实现的卡顿问题 实现效果如图: 代码实现如图: 主逻辑文件 cityList.js ...
- vue-cli 3.0 实现A-Z字母滑动选择城市列表
项目地址: https://github.com/caochangkui/vue-cli3 项目代码: 城市列表首页: City.vue <template> <div id=&qu ...
- vue 城市列表与字母表联动
实现两个联动 一是点击右侧字母的时候,城市列表出现相应首字母下的城市 二是鼠标在字母表上滑动的时候,城市列表实时跟着变化 一.点击字母出现相应的列表,给每个字母设置handleLetterClick事 ...
- 在DevExpress程序中使用GridView直接录入数据的时候,增加列表选择的功能
在我上篇随笔<在DevExpress程序中使用Winform分页控件直接录入数据并保存>中介绍了在GridView以及在其封装的分页控件上做数据的直接录入的处理,介绍情况下数据的保存和校验 ...
- Vue2.5开发去哪儿网App 城市列表开发之 兄弟组件间联动及列表性能优化
一, 兄弟组件间联动 1. 点击城市字母,左侧对应显示 给遍历的 字母 添加一个点击事件: Alphabet.vue @click="handleLetterClick" ha ...
- vue | 基于vue的城市选择器和搜索城市对应的小区
城市选择器应该是比较常用的一个组件,用户可以去选择自己的城市,选择城市后返回,又根据自己选择的城市搜索小区. 功能展示 这是选择结果 这是选择城市 这是搜索小区 这是搜索小区接口,key为城市名字,i ...
- Android例子源码非第三方实现根据字母排序的城市列表
values 下dimens.xml <resources> <!-- Default screen margins, per the Android Design guidelin ...
- Windows Phone 8.1 新特性 - 控件之列表选择控件
本篇我们来介绍Windows Phone 8.1 新特性中的列表选择控件. 在Windows Phone 8 时代,大家都会使用 LongListSelector 来实现列表选择控件,对数据进行分组显 ...
- iOS开发——UI篇&下拉弹出列表选择项效果
下拉弹出列表选择项效果 右边菜单中的按键,点击弹出一个列表可选择,选择其中一个,响应相应的事件并把文字显示在右边的菜单上:弹出下拉效果使用LMDropdownView插件,可以用POD进行加载pod ...
随机推荐
- sublime text2一些使用技巧+插件
一.前言 作为一个前端,有一款好的开发利器是必不可少的,editplus.notepad++都是不错的工具,体积轻巧,启动迅速(dw太浮肿了).最近,又有一款新的编辑器诞生,席卷前端界,惹得无数喜爱, ...
- winSocket编程(一)WSAStartup
/******************************************************************** 更新日期:2017-11-07 10:33:08* 进度:完 ...
- 1045 Favorite Color Stripe 动态规划
1045 Favorite Color Stripe 1045. Favorite Color Stripe (30)Eva is trying to make her own color strip ...
- python计算机硬件基础以及变量常量常量池,解释器编译器比较,python的两种运行方式
1.什么是编程语言 语言是一个事物与另外一个事物沟通的介质 编程语言是程序员与计算机沟通的介质 2.什么是编程 编程就是程序按照某种编程语言的语法规范将自己想要让计算机做的事情表达出来 表达的结果就是 ...
- noip第2课资料
- codeforces 982 c
给你一棵树 让你进行切割 问你最多能切多少刀 使得每个连通分量size都是偶数 思路:首先 要是有奇数个节点的话 那么不管你怎么切割 都会有一个连通分量的size是奇数 所以只有偶数的情况 ...
- [ 9.12 ]CF每日一题系列—— 960B暴力数组
Description: 给你两个数组,顺序一定,问你第一个数组连续的几个值等于下一个数组连续的几个值,然后寻找这个值得最大值,也就是满足就换 Solution: 用两个变量索引,判断即可 #incl ...
- node linux
在linux下安装nodejs 教程:http://my.oschina.net/blogshi/blog/260953 连接linux服务器,supervisor bin/www,断开连接,服务器还 ...
- 异步多线程 Thread ThreadPool Task
一.线程 Thread ThreadPool 线程是Windows任务调度的最小单位,线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针.程序计数器等),但代码区是共享的,即不同的线程可以 ...
- 调用GOOGLE的TTS实现文字转语音(XE7+小米2)(XE10.1+小米5)
相关资料: 注意:在手机上必须选安装文字转语音引擎“google Text To Speech”地址:http://www.shouji56.com/soft/GoogleWenZiZhuanYuYi ...