src>router>index.js 增加一个router
{
path: '/city',
name: 'City',
component: City
}
给header.vue中的.header-right包裹一个
此时点击城市后可以跳转但是会变色 因此给.header-right加个样式 color: #fff
没什么特别的 box-sizing: border-box padding: 0 .1rem 使得搜索输入字符离边框有段距离
.border-topbottom
&:before
border-color: #ccc
&:before
border-color: #ccc
使列表页无法拖动
.list
overflow: hidden
position: absolute
top: 1.58rem
left: 0
right: 0
bottom: 0
better-scroll插件安装
npm install better-scroll --save
先在.list里包裹一个div,再给.list加个ref="wrapper",
import Bscroll from 'better-scroll'
export default {
name: 'List',
mounted () {
this.scroll = new Bscroll(this.$refs.wrapper)
}
}
字母表 CityAlphabet.vue
.list
display: flex
flex-direction: column
justify-content: center
position: absolute
top: 1.58rem
right: 0
bottom: 0
width: .4rem
.item
text-align: center
line-height: .4rem
color: $bgColor
列表页面的动态数据的渲染
City.vue :
import axios from 'axios'
methods: {
getCityInfo () {
axios.get('/api/city.json')
.then(this.handleGetCityInfoSucc)
},
handleGetCityInfoSucc (res) {
console.log(res)
}
},
mounted () {
this.getCityInfo()
}
data () {
return {
cities: {},
hotCities: []
}
},
methods: {
...
handleGetCityInfoSucc (res) {
//console.log(res)
res = res.data
if(res.ret && res.data) {
const data = res.data
this.cities = data.cities
this.hotCities = data.hotCities
}
}
}
到子组件中接收数据:
props: {
hotCities: Array,
cities: Object
},
热门城市
{{key}}
{{innerItem.name}}
兄弟组件数据传递
希望点击右侧字母滚动到相应首字母城市列表
给alphabet中每个li绑定一个点击事件@click="handleLetterClick"
methods: {
handleLetterClick (e) {
this.$emit('change', e.target.innerText)
}
}
在父组件City.vue中 在city-alphabet中监听change事件
在data中添加 letter: ''
handleLetterChange (letter) {
this.letter = letter
}
在
:letter="letter"
在List.vue中接收数据 props里加一个 letter: String
.area绑定 :ref="key"
watch: {
letter () {
if (this.letter) {
const element = this.$refs[this.letter][0]
this.scroll.scrollToElement(element)
}
}
}
拖动实现和点击一样的效果:
首先通过computed得到数组形式的字母表
computed: {
letters () {
const letters = []
for (let i in this.cities) {
letters.push(i)
}
return letters
}
},
handleTouchStart () {
this.touchStatus = true
},
handleTouchMove (e) {
if (this.touchStatus) {
const startY = this.$refs['A'][0].offsetTop
const touchY = e.touches[0].clientY - 79
const index = Math.floor((touchY - startY) / 20)
if (index >= 0 && index < this.letters.length) {
this.$emit('change', this.letters[index])
}
}
},
handleTouchEnd () {
this.touchStatus = false
}
搜索逻辑实现
-
{{item.name}}
-
没有找到匹配数据
watch: {
keyword () {
if (this.timer) {
clearTimeout(this.timer)
}
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)
}
vuex实现数据共享
要求点击城市后,首页的城市也要跟着变
src>store>index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
city: '北京'
}
})
src>main.js
import store from './store'
new Vue({})加上store
Header.vue List.vue里都可以直接用
{{this.$store.state.city}}
希望点击城市后当前城市相应改变
city>components>city.vue
给.button-wrapper加一个点击事件 @click="handleCityClick(item.name)
methods: {
handleCityClick (city) {
this.$store.dispatch('changeCity', city)
this.$router.push('/') // 点击城市返回首页
}
},
src>store>index.js
actions: {
changeCity (ctx, city) {
ctx.commit('changeCity', city)
}
},
mutations: {
changeCity (state, city) {
state.city = city
}
}
用localStorage存储上次选择的城市
为避免如果用户关闭了localStorage可能导致发生异常,在外层加一层try catch
let defaultCity = '上海'
try {
if (localStorage.city) {
defaultCity = localStorage.city
}
} catch (e) {}
export default new Vuex.Store({
state: {
city: defaultCity
},
mutations: {
changeCity (state, city) {
state.city = city
try {
localStorage.city = city
} catch (e) {}
}
}
})
使用keep-alive优化网页性能
表示路由内容被加载过一次之后就保存在内存之中
当改变当前城市后需要改变内容
activated () {
if (this.lastCity !== this.city) {
this.lastCity = this.city
this.getHomeInfo()
}
}
类似