项目介绍
本项目是通过慕课网来学习的vue项目,因为公司比较忙,所以一段时间只能停下来。现在也算是终于写完了,因为没有本地服务器和后台支持,现在用的json文件调用。
项目引用插件
fastClick.attach(document.body)
babel-polyfill:提供es6有而es5没有的一些方法,相当于一个es5的装备,装上之后能让他使用es6的方法
vue-awesome-swiper:vue的swiper插件 引用方式:main.js Vue.use(VueAwesomeSwiper)
项目中vue-router&vuex,都是分别单独放在router和store文件夹下
项目组成
项目中分为首页,城市列表页,以及旅游项目详情页。
分别对应Home.vue city.vue detail.vue
首页 home.vue
构成:基本组件构建加vue-awesome-swiper 实现轮播。
(list.vue包含Recommend.vue和Weekend.vue。因为都是v-for循环出来的数据,很基础 这里就不做总结了)
home.vue 中的一个组件为icon.vue
这个组件每一个icon是一条数据,对于这个分页 ,同样采用swiper插件,那么第一页显示8条,剩余第二页就需要计算,在这里采用计算属性computed 定一个page(),创建一个pages变量,把父组件传来的值iconlist进行分组,8个一组,
进行分页展示
computed: {
pages () {
const pages = []
this.iconlist.forEach((item, index) => {
const page = Math.floor(index / 8)
if (!pages[page]) {
pages[page] = []
}
pages[page].push(item)
})
return pages
}
}
home.vue其他的组件还是比较简单的,基本就是v-for对数据的循环。这里就不总结了。
城市列表页 city.vue
首先显示头部组件,当前城市和热门城市组件,城市搜索组件
头部组件:页面标题加返回按钮 这个没什么说的。
搜索组件:一个input框,这里用padding撑开(兼容),在页面上有一个灰色的不透明遮罩。v-show='hasNoData'来判断是否有数据来进行数据展示和友情提示。HasNoData是通过计算属性,把父组件传来的list的的长度作为判断条件
computed: {
hasNoData () {
return !this.list.length
}
}
result,然后再赋值给list,在模板中循环就ok。
(部分数据展示)
<script type="es6">
import Bscroll from 'better-scroll'
import { mapMutations } from 'vuex'
export default {
name: 'CitySearch',
props: {
citylist: Object
},
data () {
return {
keyword: '',
list: [],
times: null
}
},
methods: {
handleCityClick (city) {
// this.$store.commit('changeCity', city)
this.changeCity(city)
this.$router.push('/')
},
...mapMutations(['changeCity'])
},
computed: {
hasNoData () {
return !this.list.length
}
},
watch: {
keyword () {
if (this.times) {
clearTimeout(this.times)
}
if (!this.keyword) {
this.list = []
return
}
this.times = setTimeout(() => {
const result = []
for (let i in this.citylist) {
this.citylist[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>
Alphabet.vue组件 ,根据字母滑动迅速定位到该字母的城市。
<template>
<div>
<ul class="list">
<li class="item"
v-for="item of letters"
:key="item"
:ref="item"
@click="handleLetterClick"
@touchstart.prevent="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
>
{{item}}
</li>
</ul>
</div>
</template>
updated () {
this.startY = this.$refs['A'][0].offsetTop
},
computed: {
letters () {
const letters = []
for (let i in this.citylist) {
letters.push(i)
}
return letters
}
},
methods: {
handleLetterClick (e) {
this.$emit('change', e.target.innerText)
},
handleTouchStart () {
this.touchStatus = true
},
handleTouchMove (e) {
if (this.touchStatus) {
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])
}
}, 16)
}
},
handleTouchEnd () {
this.touchStatus = false
}
}
通过计算属性把父组件传来的值进行循环,取出key值(A,B,C...),v-for循环key值,展示在页面。
滑动定位当前字母位置:首先三个事件,touchStart(开启滚动),touchMove(手指移动),touchEnd(停止滚动),
Math.floor((touchY - this.startY) / 20),这样算出来的就是每个字母对应的下标,这样我们就能得到letters里面的数据,再传给父类,
父类再传给子组件CityList组件,再利用better-scroll提供的this.scroll.scrollToElement(element)方法,把对应的对象传进去就会自定滑到对应位置,所以在页面上直接通过父组件传来的litter就可以迅速定位到自己滑动的字母对应的位置。