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

项目地址:
https://github.com/caochangkui/vue-cli3
项目代码:
城市列表首页:
City.vue
<template>
<div id="city">
<!-- <img src="/logo.png" alt="" height="10px"> -->
<div class="word" v-show="showWord">
<span>{{letter}}</span>
</div>
<div class="title">城市选择</div>
<city-list
:cities="cities"
:hot="hotCities"
:letter="letter"
></city-list>
<city-alphabet
:cities="cities"
@change="handleLetterChange"
></city-alphabet>
</div>
</template>
<script>
import axios from 'axios'
import CityList from './components/List'
import CityAlphabet from './components/Alphabet'
export default {
name: 'City',
components: {
CityList,
CityAlphabet
},
data () {
return {
showWord: false,
cities: {},
hotCities: [],
letter: ''
}
},
methods: {
getCityInfo () {
axios.get('/mock/city.json').then(this.handleGetCityInfoSucc)
},
handleGetCityInfoSucc (res) {
console.log(res.data)
res = res.data
if (res.ret && res.data) {
const data = res.data
this.cities = data.cities
this.hotCities = data.hotCities
}
},
handleLetterChange (letter) {
console.log(letter)
this.letter = letter
this.showWord = true
setTimeout(() => {
this.showWord = false
console.log(this.showWord)
}, 500)
}
},
mounted () {
this.getCityInfo()
}
}
</script>
<style scoped>
.title {
line-height: 40px;
background: #10d1eb;
color: #fff;
}
.word {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
z-index: 99;
}
.word span {
display: inline-block;
height: 60px;
width: 60px;
background: rgba(0, 0, 0, .2);
display: flex;
justify-content: center;
align-items: center;
}
</style>
城市列表组件:
List.vue
<template>
<div class="list" ref="wrapper">
<div>
<div class="area">
<div class="title">当前城市</div>
<div class="button-list">
<div class="button-wrapper">
<div class="button">{{this.currentCity}}</div>
</div>
</div>
</div>
<div class="area">
<div class="title">热门城市</div>
<div class="button-list">
<div
class="button-wrapper"
v-for="item in hot"
:key="item.id"
@click="handleCityClick(item.name)"
>
<div class="button">{{item.name}}</div>
</div>
</div>
</div>
<div
class="area"
v-for="(item, index) in cities"
:key="index"
:ref="index"
>
<div class="title">{{index}}</div>
<div
class="item-list"
v-for="innerItem in item"
:key=innerItem.id
@click="handleCityClick(innerItem.name)"
>
<div class="item"> {{innerItem.name}} </div>
</div>
</div>
</div>
</div>
</template>
<script>
import Bscroll from 'better-scroll'
import { mapState, mapMutations } from 'vuex'
export default {
name: 'CityList',
props: {
hot: Array,
cities: Object,
letter: String
},
data () {
return {
}
},
computed: {
...mapState({
currentCity: 'city'
})
},
watch: {
// 监听 Alphabet 中传过来的letter,如有变化,则滚动区域自动滚动到对应元素上
letter () {
if (this.letter) {
const element = this.$refs[this.letter][0] // 获取对应字母的ref
this.scroll.scrollToElement(element) // 利用better-scroll插件 滚动到指定元素element
console.log(element)
}
}
},
methods: {
...mapMutations(['changeCity']),
handleCityClick (city) {
console.log(city)
// this.$store.commit('changeCity', city) // 将参数city传给vuex中的mutations中的changeCity函数
this.changeCity(city)
this.$router.push('/') // 页面跳转 参考
}
},
mounted () {
this.scroll = new Bscroll(this.$refs.wrapper, {
click: true
})
},
}
</script>
<style scoped>
.list {
position: absolute;
top: 40px;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
}
.title {
line-height: 40px;
background: #eee;
padding-left: 10px;
color: #666;
font-size: 14px;
text-align: left;
}
.button-list {
overflow: hidden;
padding: 10px 30px 10px 10px;
}
.button-wrapper {
float: left;
width: 33.33%;
}
.button {
margin: 4px;
padding: 4px 0;
text-align: center;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 14px;
color: #555;
}
.item {
line-height: 40px;
padding-left: 16px;
text-align: left;
border-bottom: 1px solid #eee;
}
</style>
字母检索组件:
Alphabet.vue
<template>
<div class="list-wrapper">
<ul class="list">
<li class="item"
v-for="item of letters"
:key="item"
:ref="item"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
@click="handleLetterClick"
>{{item}}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'CityAlphabet',
props: {
cities: Object
},
data () {
return {
touchStatus: false,
startY: 0,
timeer: null
}
},
computed: {
letters () {
const letters = []
for (let i in this.cities) {
letters.push(i)
}
return letters
}
},
// 生命周期函数
updated () {
this.startY = this.$refs['A'][0].offsetTop // A字母距离滚动条顶部距离
console.log('updated---> ', this.startY)
},
methods: {
handleLetterClick (e) {
this.$emit('change', e.target.innerText)
console.log(1)
},
handleTouchStart () {
console.log('开始滑动')
this.touchStatus = true
},
handleTouchMove (e) {
if (this.touchStatus) {
if (this.timeer) {
clearTimeout(this.timeer)
}
this.timeer = setTimeout(() => {
console.log(e.touches[0])
const touchY = e.touches[0].clientY - 40 // 手指触摸当前位置距离视口顶部的距离减去40(40指滚动区域最上边和页面顶部之间的距离)
const index = Math.floor((touchY - this.startY) / 26) // 手指触摸当前位置所在的字母索引(26指单个字母的高度)
if (index >= 0 && index < this.letters.length) {
this.$emit('change', this.letters[index])
}
}, 16)
}
},
handleTouchEnd () {
this.touchStatus = false
}
}
}
</script>
<style scoped>
.list {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: absolute;
right: 0;
top: 40px;
bottom: 0;
width: 30px;
list-style: none;
background: rgba(0, 0, 0, .2);
margin: 0;
padding: 0;
z-index: 999;
}
.item {
line-height: 24px;
color: #068b9c;
font-size: 14px;
text-align: center;
width: 100%;
}
</style>
通过vuex管理已选城市:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let defaultCity = '北京'
try {
if (localStorage.city) {
defaultCity = localStorage.city
}
} catch (e) {e}
const state = {
count: 1,
city: defaultCity
}
const mutations = {
changeCity (state, city) {
state.city = city
try {
localStorage.city = city
} catch (e) {e}
}
}
const actions = {
}
export default new Vuex.Store({
state,
mutations,
actions
})
vue-cli 3.0 实现A-Z字母滑动选择城市列表的更多相关文章
- VUE CLI 3.0 安装及创建项目
一.安装 VUE CLI 3.0 官网: https://cli.vuejs.org/ 详细资料可以自己先把官网过一遍. 1. 安装(默认你的电脑上已安装node及npm) npm install ...
- @vue/cli 3.0 使用 svg-sprite-loader 加载本地 SVG 文件
目录 @vue/cli 3.0 使用 svg-sprite-loader 加载本地 SVG 文件 运行 使用 配置 svg-sprite-loader 调用当前环境下的颜色 props @vue/cl ...
- Vue CLI 3.0脚手架如何在本地配置mock数据
前后端分离的开发模式已经是目前前端的主流模式,至于为什么会前后端分离的开发我们就不做过多的阐述,既然是前后端分离的模式开发肯定是离不开前端的数据模拟阶段. 我们在开发的过程中,由于后台接口的没有完成或 ...
- 如何使用@vue/cli 3.0在npm上创建,发布和使用你自己的Vue.js组件库
译者按: 你可能npm人家的包过成千上万次,但你是否有创建,发布和使用过自己的npm包? 原文: How to create, publish and use your own VueJS Compo ...
- Django + Vue cli 3.0 访问静态资源问题
[问题背景] 用Vue clie 3.0的搭建得框架把我坑死了,在打包后,调用不到静态资源js,css,mp3等 [问题原因] vue cli 3.0打包后,dist目录下没有static目录,而Dj ...
- 专访Vue作者尤雨溪:Vue CLI 3.0重构的原因
1.为什么要对 Vue CLI 进行大规模修改? 尤雨溪认为旧版本的 Vue CLI 本质上只是从 GitHub 拉取模版,这种拉模版的方式有几个问题: (1) 在单个模版里面同时支持太多选项会导致模 ...
- vue cli 4.0.5 的使用
vue cli 4.0.5 的使用 现在的 vue 脚手架已经升级到4.0的版本了,前两日vue 刚发布了3.0版本,我看了一下cli 4 和cli 3 没什么区别,既然这样,就只总结一下vue cl ...
- vue/cli 3.0脚手架搭建
在vue 2.9.6中,搭建vue-cli脚手架的流程是这样的: 首先 全局安装vue-cli,在cmd中输入命令: npm install --global vue-cli 安装成功: 安装完成 ...
- @vue/cli 4.0+express 前后端分离实践
之前总结过一篇vue-cli 2.x+express+json-server实现前后端分离的帖子,@vue/cli3.0及4.0搭建的项目与vue-cli2.x的项目结构有很大的不同.这里对@vue/ ...
随机推荐
- 使用 PowerShell 创建 Azure VM 的自定义映像
自定义映像类似于应用商店映像,不同的是自定义映像的创建者是你自己. 自定义映像可用于启动配置,例如预加载应用程序.应用程序配置和其他 OS 配置. 在本教程中,你将创建自己的 Azure 虚拟机自定义 ...
- Oracle EBS OPM 子库存转移
--子库存转移 --created by jenrry DECLARE l_mtl_txn_rec mtl_transactions_interface%ROWTYPE; l_mtl_txn_lot_ ...
- Lorem 占位符
Web开发者通常用lorem ipsum text来做占位符,占位符就是占着位置的一些文字,没有实际意义. 为什么叫lorem ipsum text呢? 是因为lorem ipsum是古罗马西塞罗谚语 ...
- 类Unix上5个最佳开源备份工具 Bacula/Amanda/Backupninja/Backuppc/UrBackup
当为一个企业选择备份工具的时候,你都考虑什么呢? 确定你正在部署的软件具有下面的特性 开源软件 – 你务必要选择那些源码可以免费获得,并且可以修改的软件.确信可以恢复你的数据,即使是软件供应商/项目停 ...
- QT的setwindowflags的属性总结
:setWindowFlags(Qt::CustomizeWindowHint);//设置窗口标题栏自定义 setWindowFlags(Qt::WindowMinimizeButtonHint);/ ...
- 团队作业6--展示博客(Alpha版本)
一.团队展示: 1.队名:软件1412--博客管理系统 2.队员学号(标记组长) 曾海明(组长):201421122036 周雅静(组员):201421122003 王珏(组员):2014211 ...
- Flink 的广播变量
Flink 支持广播变量,就是将数据广播到具体的 taskmanager 上,数据存储在内存中,这样可以减缓大量的 shuffle 操作: 比如在数据 join 阶段,不可避免的就是大量的 shuff ...
- ECStore图片云端集群存储实践-又拍云存储
通过又拍云存储REST API ,为ECStore新增图片存储引擎,从而达到图片数据与主站数据分离.提高网站性能. 图片存储引擎相关文件添加与修改 一共涉及到ECStore 2个APP 的文件添加和修 ...
- sql优化常见的集中方法
在sql查询中为了提高查询效率,我们常常会采取一些措施对查询语句进行sql优化,下面总结的一些方法,有需要的可以参考参考. 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 ord ...
- 当我们跑SparkSQL时候为了更好地了解SparkSQL运行,可以WEBUI看SQL的Tab