最后的成果就是下面所展示的内容,因为gif图没有做,只能截图所展示,接下来,会带着大家一步一步的完成下面功能,脚手架搭建和node安装在本次案例不会讲解,如果了解,可以在我的博客园找到有详细介绍
准备工作:
引入axios插件,调用better-scroll第三方插件,本地json文件,可以参考目录中的city.json,有条件的也可以自己去扒
功能分析
1.获取json数据展示城市列表 。
2.侧边字母定位滚动到相应的位置。
3.实现搜索城市
接下来我们开始对组件进行划分:本次案例中,总共划分为五个组件,下面就是组件的划分图
创建city组件,通过父组件获取数据,传递给子组件
<template> <div> <CityHeader></CityHeader> //头部 <Search :list="cities"></Search> //搜索 <List :hot="hotCity" :letter="letter" :list="cities"></List> //城市列表 <Alphabet @chang="handleLetterChang" :list="cities"></Alphabet> //A-Z </div> </template> <script> import axios from 'axios' import CityHeader from './components/Header' import Search from './components/Search' import List from './components/List' import Alphabet from './components/Alphabet' export default { data () { return { cities:{}, // 城市列表 hotCity:[], //热门城市 letter: '' // A-Z } }, components: { CityHeader, Search, List, Alphabet }, methods:{ getCityInfo () { axios.get('/api/city.json').then(this.getCityInfoSucc) }, getCityInfoSucc(res){ res = res.data if (res.ret && res.data) { const data = res.data this.hotCity = data.hotCities this.cities = data.cities } console.log(this.cities) }, handleLetterChang(letter) { //接受子组件传过来的 // console.log(letter) this.letter = letter } }, mounted () { this.getCityInfo () } } </script> <style scoped lang="stylus"> </style>
把得到的数据分次传递个对应的子组件,这样有利于网站优化,不用频繁的请数据
<template> <div> <CityHeader></CityHeader> <Search :list="cities"></Search> <List :hot="hotCity" :letter="letter" :list="cities"></List> <Alphabet @chang="handleLetterChang" :list="cities"></Alphabet> </div> </template> export default { data () { return { cities:{}, // 城市列表 hotCity:[], //热门城市 letter: '' // A-Z } }, components: { CityHeader, Search, List, Alphabet }, methods:{ getCityInfo () { axios.get('/api/city.json').then(this.getCityInfoSucc) //请求本地配置的mock数据 }, getCityInfoSucc(res){ res = res.data if (res.ret && res.data) { const data = res.data this.hotCity = data.hotCities this.cities = data.cities } } }, mounted () { this.getCityInfo () } }
创建头部组件,
<template> <div> 城市选择 <router-link to="https://www.jb51.net/"> <div></div> </router-link> </div> </template> <script> export default { } </script> <style scoped lang="stylus"> @import '~styles/varibles.styl'; @import '~styles/mixins.styl'; .header overflow: hidden height $headerHeight line-height: $headerHeight text-align: center color: #fff background: $bgColor font-size: .4rem .back-icon position: absolute left: 0 top: 0 width: .64rem font-size: .4rem text-align: center color: #fff </style>
创建搜索组件页面,接受父组件传递的数据,引入better-scroll第三方插件,实现列表滚动
<template> <div> <div> <input v-model="keyword" type="text" placeholder="输入城市名或者拼音" /> </div> <div ref="search" v-show="keyword"> <ul> <li v-for="item in listItem" :key="item.id">{{item.name}}</li> <li v-show="hasNoData">没有搜索到匹配的数据</li> </ul> </div> </div> </template> <script> import BScroll from 'better-scroll' export default { props: { list: Object, }, data() { return { keyword:'', listItem:[], timer:null } }, computed: { hasNoData() { return !this.listItem.length //没有搜索的条件是否显示 } }, watch: { keyword () { if (this.timer) { clearTimeout(this.timer) } if(!this.keyword) { //清空 this.listItem = "" return } this.timer = setTimeout(() => { const result = [] for (let i in this.list) { this.list[i].forEach((value) => { //匹配搜索的条件 if (value.spell.indexOf(this.keyword) > -1 || value.name.indexOf(this.keyword) > -1) { result.push(value) } }) } this.listItem= result },100) } }, mounted () { this.scroll = new BScroll(this.$refs.search) } } </script> <style scoped lang="stylus"> @import '~styles/varibles.styl' @import '~styles/mixins.styl' .search height: .72rem padding: 0 .1rem background:$bgColor .search-input box-sizing: border-box width:100% height: .62rem line-height: .62rem text-align: center border-radius: .06rem padding: 0 .1rem color: #666 .search-content z-index: 1 overflow:hidden position:absolute top: 1.58rem left: 0 right: 0 bottom: 0 background: #eee .serach-item line-height: .62rem padding-left:.2rem color:#666 background: #fff </style>
创建城市列表组件,引入better-scroll插件,实现列表滚动,通过watch监听letter,实现字母与城市列表滚动