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

//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. 使用CEfSharp之旅(6)拦截网络请求 截取response返回

    原文:使用CEfSharp之旅(6)拦截网络请求 截取response返回 版权声明:本文为博主原创文章,未经博主允许不得转载.可点击关注博主 ,不明白的进群191065815 我的群里问 https ...

  2. mysql的建表约束

    主键约束(primary key) 主键约束能够唯一确定一张表中的记录,也就是可以通过某个字段添加约束,就可以是的该字段不重复,且不为空 create table user (id int prima ...

  3. 如何使用Spark大规模并行构建索引

    使用Spark构建索引非常简单,因为spark提供了更高级的抽象rdd分布式弹性数据集,相比以前的使用Hadoop的MapReduce来构建大规模索引,Spark具有更灵活的api操作,性能更高,语法 ...

  4. UMP系统架构 Controller服务器

  5. (转)常用的三种修改mysql最大连接数的方法

    MYSQL数据库安装完成后,默认最大连接数是100,一般流量稍微大一点的论坛或网站这个连接数是远远不够的,增加默认MYSQL连接数的方法有两个 方法一:进入MYSQL安装目录 打开MYSQL配置文件 ...

  6. 【主席树】 [CQOI2015]任务查询系统

    模板题... 差分,然后用主席树维护时间点上的优先值和就好了 就是细节烦... #include<bits/stdc++.h> #define int long long #define ...

  7. Educational Codeforces Round49

    A Palindromic Twist(字符串) 问每个字母必须向左或向右变成另一个字母,问能不能构成回文 #include <iostream> #include <string. ...

  8. LJJ爱数数

    LJJ爱数数 求\(\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^n\epsilon(gcd(i,j,k))(\frac{1}{i}+\frac{1}{j}==\frac{1} ...

  9. [转]Entity Framework 的实体关系

    通过 Entiy Framework实践系列 文章,理了理 Entity Framework 的实体关系. 为什么要写文章来理清这些关系?“血”的教训啊,刚开始使用 Entity Framework  ...

  10. csp-s模拟65Simple,Walk, Travel,棋盘题解

    题面:https://www.cnblogs.com/Juve/articles/11639923.html simple: 考试时只想到的暴力exgcd判断 考虑n,m互质的情况: 我们枚举y,对于 ...