项目地址:

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字母滑动选择城市列表的更多相关文章

  1. VUE CLI 3.0 安装及创建项目

    一.安装 VUE CLI 3.0 官网: https://cli.vuejs.org/   详细资料可以自己先把官网过一遍. 1. 安装(默认你的电脑上已安装node及npm) npm install ...

  2. @vue/cli 3.0 使用 svg-sprite-loader 加载本地 SVG 文件

    目录 @vue/cli 3.0 使用 svg-sprite-loader 加载本地 SVG 文件 运行 使用 配置 svg-sprite-loader 调用当前环境下的颜色 props @vue/cl ...

  3. Vue CLI 3.0脚手架如何在本地配置mock数据

    前后端分离的开发模式已经是目前前端的主流模式,至于为什么会前后端分离的开发我们就不做过多的阐述,既然是前后端分离的模式开发肯定是离不开前端的数据模拟阶段. 我们在开发的过程中,由于后台接口的没有完成或 ...

  4. 如何使用@vue/cli 3.0在npm上创建,发布和使用你自己的Vue.js组件库

    译者按: 你可能npm人家的包过成千上万次,但你是否有创建,发布和使用过自己的npm包? 原文: How to create, publish and use your own VueJS Compo ...

  5. Django + Vue cli 3.0 访问静态资源问题

    [问题背景] 用Vue clie 3.0的搭建得框架把我坑死了,在打包后,调用不到静态资源js,css,mp3等 [问题原因] vue cli 3.0打包后,dist目录下没有static目录,而Dj ...

  6. 专访Vue作者尤雨溪:Vue CLI 3.0重构的原因

    1.为什么要对 Vue CLI 进行大规模修改? 尤雨溪认为旧版本的 Vue CLI 本质上只是从 GitHub 拉取模版,这种拉模版的方式有几个问题: (1) 在单个模版里面同时支持太多选项会导致模 ...

  7. vue cli 4.0.5 的使用

    vue cli 4.0.5 的使用 现在的 vue 脚手架已经升级到4.0的版本了,前两日vue 刚发布了3.0版本,我看了一下cli 4 和cli 3 没什么区别,既然这样,就只总结一下vue cl ...

  8. vue/cli 3.0脚手架搭建

    在vue 2.9.6中,搭建vue-cli脚手架的流程是这样的: 首先 全局安装vue-cli,在cmd中输入命令: npm install --global vue-cli  安装成功:  安装完成 ...

  9. @vue/cli 4.0+express 前后端分离实践

    之前总结过一篇vue-cli 2.x+express+json-server实现前后端分离的帖子,@vue/cli3.0及4.0搭建的项目与vue-cli2.x的项目结构有很大的不同.这里对@vue/ ...

随机推荐

  1. Asp.Net Core使用System.Drawing.Common部署到docker报错问题

    Asp.Net Core 2.1发布后,正式支持System.Drawing.Common绘图了,可以用来做一些图片验证码之类的功能.但是把网站部署到docker容器里运行会遇到很多问题,也是非常闹心 ...

  2. python之demo2----改编自python官方提供的turtle_yinyang.py画阴阳的demo

    """ 执行 python -m turtledemo 命令查看系统内置demo的源码 绘制:需要通过import turtle引入绘制图形库turtle库 改编自pyt ...

  3. C语言的历史及个人拙见

    C语言是一个无限广阔的世界,你刚开始睁眼看它的时候以为视线的尽头就是边界,但当你慢慢走去,才发现天外有天.这或许就是江湖传说只有C才有真正高手的原因,或许我们也可以反过来说:C没有高手——因为没有人能 ...

  4. 全球首款完全开源的堡垒机,符合 4A 的专业运维审计系统Jumpserver

    Jumpserver是全球首款完全开源的堡垒机,是符合 4A 的专业运维审计系统. http://www.jumpserver.org https://github.com/jumpserver/ju ...

  5. cat > file << EOF 与 cat > file << -

    当我们在使用kickstart 的时候,会遇到写网卡配置文件的情况,这时候我们使用cat > file << EOF 命令等,可以从标准输入中接受输入并保存到 file 文件中. c ...

  6. 第四次作业 重写equals方法

    使用上几次用到得User实体类,在其中重写equals方法. @Override public boolean equals(Object obj) { if(obj==null)return fal ...

  7. Hadoop HBase概念学习系列之HMaster服务器(四)

    每台HRegion服务器都会和HMaster服务器通信,HMaster的主要任务就是告诉每个HRegion服务器它要维护哪些HRegion. 当一台新的HRegion服务器登录到HMaster服务器时 ...

  8. 3675: [Apio2014]序列分割

    Description 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了得到k+1个子序列,小H需要重复k次以下的步骤: 1.小H首 ...

  9. HTTP 请求头中的 X-Forwarded-For,X-Real-IP

     X-Forwarded-For 在使用nginx做反向代理时,我们为了记录整个的代理过程,我们往往会在配置文件中做如下配置: location / { 省略... proxy_set_header ...

  10. helm 部署

    Helm 基本概念 Helm 可以理解为 Kubernetes 的包管理工具,可以方便地发现.共享和使用为Kubernetes构建的应用,它包含几个基本概念 Chart:一个 Helm 包,其中包含了 ...