項目介紹
本項目是通過慕課網來學習的vue項目,因為公司比較忙,所以一段時間只能停下來。現在也算是終於寫完了,因為沒有本地服務器和后台支持,現在用的json文件調用。
項目引用插件
fastclick:處理移動端click事件300毫秒延遲 引用方式:main.js 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
}
}
在輸入框搜索,進行匹配的可以是文字也可以是拼音,通過父組件傳來的citylist循環遍歷,再把每個citylist[i]遍歷出來,就是每個數據的對象,進行匹配的文字和拼音就是name字段和spell字段,然后添加到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(停止滾動),
touchMove:touchY(手指滑動的位置),startY(首字母A的位置),因為css設計每個字母的寬高均為20,也就是說計算下標只需要Math.floor((touchY - this.startY) / 20),這樣算出來的就是每個字母對應的下標,這樣我們就能得到letters里面的數據,再傳給父類,
父類再傳給子組件CityList組件,再利用better-scroll提供的this.scroll.scrollToElement(element)方法,把對應的對象傳進去就會自定滑到對應位置,所以在頁面上直接通過父組件傳來的litter就可以迅速定位到自己滑動的字母對應的位置。