接下来我们对城市列表页面进行优化,除了对数据优化,也会进行节流处理

//src\pages\city\components\Alphabet.vue
<template>
<ul class="list">
<li class="item"
v-for="item of letters"
@click="handleLetterClick"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
:key="item"
:ref="item"
>{{item}}</li>
<!-- <li class="item">B</li>
<li class="item">C</li>
<li class="item">D</li>
<li class="item">E</li>
<li class="item">F</li>
<li class="item">G</li> -->
</ul>
</template>
<script>
import { clearTimeout, setTimeout } from 'timers'
export default {
name: 'CityAlphabet',
props: {
cities: Object
},
computed: {
letters () {
const letters = []
for (let i in this.cities) {
letters.push(i)
}
return letters
}
},
data () {
return {
touchStatus: false,
startY: 0,
timer: null
}
},
updated () {
this.startY = this.$refs['A'][0].offsetTop
},
methods: {
handleLetterClick (e) {
this.$emit('change', e.target.innerText)
// console.log('e.target.innerText', e.target.innerText)
},
handleTouchStart () {
this.touchStatus = true
},
handleTouchMove (e) {
if (this.touchStatus) {
// const startY = this.$refs['A'][0].offsetTop
// console.log(startY)
if (this.timer) {
clearTimeout(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.letters.length) {
this.$emit('change', this.letters[index])
}
console.log(touchY)
}, 16)
}
},
handleTouchEnd () {
this.touchStatus = false
}
}
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl';
.list
display:flex
flex-direction:column
justify-content:center
top:1.58rem
right:0
bottom:0
width:.4rem
position:absolute
.item
text-align:center
line-height:.4rem
text-align:center
color:$bgColor
</style>

接下来我们来进行搜索列表的实现

<template>
<div>
<div class="search">
<input type="text"
v-model="keyword"
class="search-input"
placeholder="请输入城市名或拼音">
</div>
<div class="search-content"
ref="search"
v-show="keyword"
>
<ul>
<li
:key="item.id"
v-for="item of list"
class="search-item border-bottom">
{{item.name}}
</li>
<li
class="search-item border-bottom"
v-show="!list.length"
>
没有找到匹配数据
</li>
</ul>
</div>
</div>
</template>
<script>
import { clearTimeout, setTimeout } from 'timers'
// 解决搜索框内容不能滚动
import Bscroll from 'better-scroll'
export default {
name: 'CitySearch',
props: {
cities: Object
},
data () {
return {
keyword: '',
list: [],
timer: null
}
},
computed: {
hasNoData () {
return !this.list.length
}
},
watch: {
keyword () {
if (this.timer) {
clearTimeout(this.timer)
}
if (!this.keyword) {
this.list = []
return
}
this.timer = setTimeout(() => {
const result = []
for (let i in this.cities) {
this.cities[i].forEach((value) => {
if (value.spell.indexOf(this.keyword) > -1 || value.name.indexOf(this.keyword) > -1) {
result.push(value)
}
})
}
this.list = result
}, 100)
}
},
mounted () {
this.scroll = new Bscroll(this.$refs.search)
}
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl';
.search
height:.72rem
background:$bgColor
padding:0 .1rem
.search-input
box-sizing:border-box
height:.62rem
width:100%
line-height:.62rem
text-align:center
border-radius:.06rem
color:#666
.search-content
z-index:1
overflow:hidden
position:absolute
top:1.58rem
left:0
right:0
bottom:0
background:#eee
.search-item
line-height:.62rem
padding-left:.2rem
background:#fff
color:#666 </style>

我们看下效果



接下来我们使用vuex进行城市定位选择,也就是城市选择页面的数据要传递给首页,也就是City组件中的数据要传递给home组件中

安装vuex

 cnpm install vuex --save

先看下实现的效果



代码如下

<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">{{this.$store.state.city}}</div>
</div>
</div>
</div>
<div class="area">
<div class="title border-topbottom">
热门城市
</div>
<div class="button-list">
<div
class="button-wrapper"
v-for="item of hot"
:key="item.id"
@click="handleCityClick(item.name)"
>
<div class="button">{{item.name}}</div>
</div>
<!-- <div class="button-wrapper">
<div class="button">北京</div>
</div>
<div class="button-wrapper">
<div class="button">北京</div>
</div>
<div class="button-wrapper">
<div class="button">北京</div>
</div>
<div class="button-wrapper">
<div class="button">北京</div>
</div>
<div class="button-wrapper">
<div class="button">北京</div>
</div> -->
</div>
</div>
<div class="area"
v-for="(item,key) of cities"
:key="key"
:ref="key"
>
<div class="title border-topbottom">
{{key}}
</div>
<div class="item-list">
<div class="item border-bottom"
v-for="innerItem of item"
:key="innerItem.id"
@click="handleCityClick(innerItem.name)"
>
{{innerItem.name}}
</div>
<!-- <div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div> -->
</div>
</div>
<!-- <div class="area">
<div class="title border-topbottom">
B
</div>
<div class="item-list">
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
</div>
</div> -->
<!-- <div class="area">
<div class="title border-topbottom">
C
</div>
<div class="item-list">
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
</div>
</div> -->
</div>
</div>
</template>
<script>
import Bscroll from 'better-scroll'
export default {
name: 'CityList',
props: {
hot: Array,
cities: Object,
letter: String
},
methods: {
handleCityClick (city) {
// this.$store.dispatch('changeCity', city)
this.$store.commit('changeCity', city)
this.$router.push('/')
// alert(city)
}
},
watch: {
letter () {
// console.log('this.letter', this.letter)
if (this.letter) {
const element = this.$refs[this.letter][0]
console.log('element', element)
this.scroll.scrollToElement(element)
}
}
},
mounted () {
this.scroll = new Bscroll(this.$refs.wrapper)
}
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl';
.border-topbottom
&:before
border-color:#ccc
&:after
border-color:#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
padding:.1rem .6rem .1rem .1rem
overflow:hidden
.button-wrapper
width:33.33%
float:left
.button
margin:.1rem
text-align:center
border:.02rem solid #ccc
border-radius:.06rem
padding:.1rem 0
.item-list
.item
line-height:.76rem
color:#666
padding-left:.2rem
</style>

接下来我们使用localstorage存储数据,使刷新的时候,也能记住我们选择的城市,另外代码还做了隐身模式或者浏览器不能保存数据的处理

//index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let defaultCity = '上海'
try {
if (localStorage.city) {
defaultCity = localStorage.city
}
} catch (e) { } export default new Vuex.Store({
state: {
// city: localStorage.city || '上海'
city: defaultCity
},
// actions: {
// changeCity (ctx, city) {
// ctx.commit('changeCity', city)
// }
// },
mutations: {
changeCity (state, city) {
state.city = city
try {
localStorage.city = city
} catch (e) { }
// localStorage.city = city
}
}
})

接下来我们来拆分index.js文件,将store中的内容按照state,mutation等进行处理

//state.js
let defaultCity = '上海'
try {
if (localStorage.city) {
defaultCity = localStorage.city
}
} catch (e) {}
export default {
city: defaultCity
}
//mutations.js
export default {
changeCity (state, city) {
state.city = city
try {
localStorage.city = city
} catch (e) { }
// localStorage.city = city
}
}
//index.js
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import mutations from './mutations'
Vue.use(Vuex)
// let defaultCity = '上海'
// try {
// if (localStorage.city) {
// defaultCity = localStorage.city
// }
// } catch (e) { // } export default new Vuex.Store({
state,
// actions: {
// changeCity (ctx, city) {
// ctx.commit('changeCity', city)
// }
// },
mutations
})
//header.vue
<template>
<div class="header">
<div class="header-left">
<div class="iconfont back-icon"></div>
</div>
<div class="header-input">
<span class="iconfont"></span>
输入城市/游玩主题</div>
<router-link to="/city">
<div class="header-right">
{{this.city}}
<span class="iconfont arrow-icon"></span>
</div>
</router-link>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
// 1rem = html font-size=50px
name: 'HomeHeader',
computed: {
...mapState(
[
'city'
]
)
},
props: {
// city: String
}
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.header
line-height:$headerHeight
background:$bgColor
color:#fff
display:flex
.header-left
width:0.64rem
float:left
.back-icon
text-align:center
font-size:0.4rem
.header-input
margin-top: 0.12rem;
line-height: 0.64rem;
-webkit-box-flex: 1;
-ms-flex: 1;
margin-bottom: 0.12rem;
flex: 1;
background: #fff;
padding-left: 0.1rem;
border-radius: 0.1rem;
color: #ccc;
.header-right
min-width:1.04rem
padding:0 .1rem
float:right
text-align:center
color:#fff
.arrow-icon
margin-left:-.04rem
font-size:.24rem
</style>
//list.vue
<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">{{this.currentCity}}</div>
</div>
</div>
</div>
<div class="area">
<div class="title border-topbottom">
热门城市
</div>
<div class="button-list">
<div
class="button-wrapper"
v-for="item of hot"
:key="item.id"
@click="handleCityClick(item.name)"
>
<div class="button">{{item.name}}</div>
</div>
<!-- <div class="button-wrapper">
<div class="button">北京</div>
</div>
<div class="button-wrapper">
<div class="button">北京</div>
</div>
<div class="button-wrapper">
<div class="button">北京</div>
</div>
<div class="button-wrapper">
<div class="button">北京</div>
</div>
<div class="button-wrapper">
<div class="button">北京</div>
</div> -->
</div>
</div>
<div class="area"
v-for="(item,key) of cities"
:key="key"
:ref="key"
>
<div class="title border-topbottom">
{{key}}
</div>
<div class="item-list">
<div class="item border-bottom"
v-for="innerItem of item"
:key="innerItem.id"
@click="handleCityClick(innerItem.name)"
>
{{innerItem.name}}
</div>
<!-- <div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div> -->
</div>
</div>
<!-- <div class="area">
<div class="title border-topbottom">
B
</div>
<div class="item-list">
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
</div>
</div> -->
<!-- <div class="area">
<div class="title border-topbottom">
C
</div>
<div class="item-list">
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</div>
<div class="item border-bottom">阿拉尔</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
},
computed: {
...mapState({
currentCity: 'city'
})
},
methods: {
handleCityClick (city) {
// this.$store.dispatch('changeCity', city)
// this.$store.commit('changeCity', city)
this.changeCity(city)
this.$router.push('/')
// alert(city)
},
...mapMutations(['changeCity'])
},
watch: {
letter () {
// console.log('this.letter', this.letter)
if (this.letter) {
const element = this.$refs[this.letter][0]
console.log('element', element)
this.scroll.scrollToElement(element)
}
}
},
mounted () {
this.scroll = new Bscroll(this.$refs.wrapper)
}
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl';
.border-topbottom
&:before
border-color:#ccc
&:after
border-color:#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
padding:.1rem .6rem .1rem .1rem
overflow:hidden
.button-wrapper
width:33.33%
float:left
.button
margin:.1rem
text-align:center
border:.02rem solid #ccc
border-radius:.06rem
padding:.1rem 0
.item-list
.item
line-height:.76rem
color:#666
padding-left:.2rem
</style>

接下来我们使用keep-alive优化网页性能

路由发生改变,请求就会进行多次

keep-alive进行缓存

//app.vue 请求之后就放内存中    从内存中取数据,不用再去请求
<template>
<div id="app">
<!-- 当前路由地址所对应的内容 -->
<keep-alive>
<!-- 缓存 -->
<router-view/>
</keep-alive>
</div>
</template> <script>
export default {
name: 'App'
}
</script> <style> </style>

使用keep-alive的时候,我们会增加生命周期函数activated

//Home.vue
<template>
<div>
<home-header ></home-header>
<home-swiper :list="swiperList"></home-swiper>
<home-icons :list="iconList"></home-icons>
<home-recommend :list="recommendList"></home-recommend>
<home-weekend :list="weekendList"></home-weekend>
</div>
</template>
<script>
import HomeHeader from './components/Header'
import HomeSwiper from './components/Swiper'
import HomeIcons from './components/Icons'
import HomeRecommend from './components/Recommend'
import HomeWeekend from './components/Weekend'
import {mapState} from 'vuex'
import axios from 'axios'
export default {
name: 'Home',
components: {
HomeHeader,
HomeSwiper,
HomeIcons,
HomeRecommend,
HomeWeekend
},
computed: {
...mapState(['city'])
},
data () {
return {
swiperList: [],
iconList: [],
recommendList: [],
weekendList: [],
lastCity: null
}
},
methods: {
getHomeInfo () {
axios.get('/api/index.json?city=' + this.city)
.then(this.getHomeInfoSucc)
},
getHomeInfoSucc (res) {
res = res.data
if (res.ret && res.data) {
const data = res.data
this.swiperList = data.swiperList
this.iconList = data.iconList
this.recommendList = data.recommendList
this.weekendList = data.weekendList
}
}
},
mounted () {
this.lastCity = this.city
this.getHomeInfo()
},
activated () {
// 页面重新显示再执行
if (this.lastCity !== this.city) {
this.lastCity = this.city
this.getHomeInfo()
}
}
}
</script>
<style>
</style>

跟我一起做一个vue的小项目(十)的更多相关文章

  1. 跟我一起做一个vue的小项目(二)

    这个vue项目是紧跟着之前的项目跟我一起做一个vue的小项目(一)来的. 我继续后面的开发(写的比较粗糙,边学边记录) 下图是header头部的样式 header组件内容如下 //header.vue ...

  2. 跟我一起做一个vue的小项目(八)

    接下来我们进行的是城市选择页面的路由配置 添加city.vue,使其点击城市,然后跳转到city页面 //router.js import Vue from 'vue' import Router f ...

  3. 跟我一起做一个vue的小项目(七)

    先看下我们所做项目的效果 这些数据都是我们在data中定义的,不是从后端数据中请求的.那么 接下来我们使用axios渲染数据 npm install axios --save 每个组件里面的数据都不相 ...

  4. 跟我一起做一个vue的小项目(五)

    接下来我们要做的是热门推荐页面,我们写一个推荐组件 使用的方法也是前端data中的数据渲染到页面上面,这里对文字过长取省略号的方法不成功使用了一个小技巧 使用了min-width:0 我们来看完整的代 ...

  5. 跟我一起做一个vue的小项目(APPvue2.5完结篇)

    先放一下这个完结项目的整体效果 下面跟我我一起进行下面项目的进行吧~~~ 接下来我们进行的是实现header的渐隐渐显效果,并且点击返回要回到首页 我们先看效果 在处理详情页向下移动过程中,heade ...

  6. 跟我一起做一个vue的小项目(四)

    接下来我们进行的是轮播页面下面的导航页的开发 我们需要的是实现轮播页下面的图标,并且实现轮播效果 这个话,其实基本思路先是渲染出小图标,然后,我们要对页数进行判断,如果图标的个数展示的就是8个,那个这 ...

  7. 跟我一起做一个vue的小项目(十一)

    接下来我们进行的是详情页动态路由及banner布局 先看页面的效果 下面是代码部分 <template> <div> <div class="banner&qu ...

  8. 跟我一起做一个vue的小项目(三)

    接下来我们进行轮播的开发 安装插件,选用2.6.7的稳定版本 npm install vue-awesome-swiper@2.6.7 --save 根据其github上面的用法,我们在全局引用,在m ...

  9. 跟我一起做一个vue的小项目(九)

    接下来我们进行的就是城市列表页面数据额动态渲染. 也是在mock数据,进行动态渲染 //city.json { "ret": true, "data":{ &q ...

随机推荐

  1. uoj#311 【UNR #2】积劳成疾

    题目 考虑直接顺着从\(1\)填数填到\(n\)发现这是在胡扯 所以考虑一些奇诡的东西,譬如最后的答案长什么样子 显然某一种方案的贡献是一个\(\prod_{i=1}^nw_i^{t_i}\)状物,\ ...

  2. html自定义分页

    public class MyPager { /// <summary> /// 每一页数据的条数 /// </summary> public int PageSize { g ...

  3. 在双重for循环内部使用async异步请求axios中遇到的问题

    在methods中的方法 async getPro () { let _this = this let newArr = [] await axios.get(`api/v1/dailyProTbms ...

  4. mybatis结果封装到hashmap中没有null的数据

    1.在ssm框架中 在mybatis-config.xml配置文件中加下面这句代码即可解决 <setting name="callSettersOnNulls" value= ...

  5. ssoj 2279 磁力阵

    说不想改最后还是向T1屈服了..然后就de了一下午Bug... 虽然昨天随口扯的有点道理,正解就是迭代加深A星搜索,但实际写起来就十分难受了. 说自己的做法,略鬼畜. 每个正方形的边界上的边.每条边在 ...

  6. 洛谷P4027 [NOI2007]货币兑换

    P4027 [NOI2007]货币兑换 算法:dp+斜率优化 题面十分冗长,题意大概是有一种金券每天价值会有变化,你可以在某些时间点买入或卖出所有的金券,问最大收益 根据题意,很容易列出朴素的状态转移 ...

  7. 解决CentOS“Zabbix discoverer processes 75% busy”的问题

    解决CentOS“Zabbix discoverer processes 75% busy”的问题 运维  立杰  4年前 (2014-08-11)  1104℃  0评论 在使用Zabbix过程中, ...

  8. ios与android设备即时语音互通的录音格式预研说明

    本文虽属原创,但是内容都是来自于网络,参考了大家的微博,以及论坛的总结. 在做语音对讲的时候,将会碰到录制语音格式的问题,因为要考虑自己开发设备的支持的格式,还要考虑其他设备操作系统的支持的格式,以及 ...

  9. 【breathandlife】气势磅礴、比较好听的旋律有哪些?

    [breathandlife]气势磅礴.比较好听的旋律有哪些? 分享:yunbest作者:来源:2015-10-26 专题:breathandlife [breathandlife]气势磅礴.比较好听 ...

  10. 新启vue_cli项目+引入Element

    [1]安装vue_cli vue init webpack 项目名字 [2]安装Element-UI cnpm install element-ui -S //写入dependencies cnpm ...