VUE去哪儿网 3 列表页面

 

路由配置 

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()
}

VUE去哪儿网 3 列表页面_第1张图片

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
},
热门城市
{{item.name}}
{{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实现数据共享

VUE去哪儿网 3 列表页面_第2张图片

要求点击城市后,首页的城市也要跟着变

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()
    }
  }

类似


  

你可能感兴趣的:(VUE去哪儿网 3 列表页面)