成果展示

最后的成果就是下面所展示的内容,因为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. 大压力下Redis参数调整要点

    调整以下参数,可以大幅度改善Redis集群的稳定性: 为何大压力下要这样调整? 最重要的原因之一Redis的主从复制,两者复制共享同一线程,虽然是异步复制的,但因为是单线程,所以也十分有限.如果主从间 ...

  2. 前端- html 和css

    html HTML 指超文本标签语言. HTML 是通向 WEB 技术世界的钥匙. html属性:所有标签的通用属性 html事件:On...html5加了很多事件 html视频/音频:处理音视频 h ...

  3. 【Andorid开发框架学习】之Mina开发之Mina简介

    今天我将介绍 Apache MINA的基本概念和 API,包括 I/O服务.I/O 会话.I/O 过滤器和 I/O 处理器. 一.MINA的简介 Apache MINA是一个网络应用程序框架,用来帮助 ...

  4. python函数知识

    一.三目运算 也叫三元运算,例如result=x if x<y else y 二.集合(set) 返回主页集合(set):把不同的元素组成一起形成集合,是python基本的数据类型.集合元素(s ...

  5. AngularJS ngTemplate寄宿方式 模板缓存 $templateCache

    AngularJS的指令中经常定义模板(template或templateUrl),可以选择将Html模板直接寄宿在WEB容器中,如Tomcat.IIS.Nginx.NodeJs Express,也可 ...

  6. 简单创建一个“嗨新房”的mac客户端

    下载地址:https://github.com/mapanguan/Mac_HiNewHouse                

  7. 5.Django高级

    管理静态文件 项目中的CSS.图片.js都是静态文件 配置静态文件 在settings 文件中定义静态内容 STATIC_URL = '/static/' STATICFILES_DIRS = [ o ...

  8. Android-Kotlin-递归与尾递归

    递归: 阶乘计算: /** * 阶乘: * 1的阶乘是1,因为1往下走一个楼梯 就是0了 * 2的阶乘是 2*1 * 3的继承是 3*2*1 * 4的继承是 4*3*2*1 * 5的阶乘是 5*4*2 ...

  9. hdu 1.2.3

    很简单的算法基础题...闰年判断以及计算 #include<iostream> #include<cstdio> using namespace std; int main() ...

  10. SQL Server nested loop join 效率试验

    从很多网页上都看到,SQL Server有三种Join的算法, nested loop join, merge join, hash join. 其中最常用的就是nested loop join. 在 ...