一、路由配置

编辑’index.js’文件(路径:src/router/index.js) - - - 创建路由的路径

import Vue from 'vue'
import VueRouter from 'vue-router'
// import Router from 'vue-router'
import Home from '@/pages/home/Home'
import City from '@/pages/city/City'Vue.use(VueRouter)
// Vue.use(Router)// export default new Router({//   routes: [{//     path: '/',
//     name: 'Home',
//     component: Home
//   }]
// })
const routes = [{path: '/',name: 'Home',component: Home},{// 创建一个路由// 路径也是根目录下的citypath: '/city',// 路由的名字叫Cityname: 'City',// 创建一个city的组件component: City}
]const router = new VueRouter({routes
})export default router

二. 组件化开发

该页面可分为’Header’、‘Search’、‘List’、'Alphabet’四个组件组成


三、City

1. 创建’City’文件夹和’City.vue’文件(路径: src/pages/city/city.vue) - - - 创建城市切换的首页

<template><div>city</div>
</template><script>
export default {name: 'City'
}
</script><style>
</style>

2.编辑’Header.vue’文件(路径: src/pages/home/components/Header.vue) - - - 在Home页设置跳转路径

在城市选择部分,包裹一层跳转路由

    <!-- 添加跳转至city的路径  但是会导致链接内容变绿色 --><router-link to="/city"><div class="header-right"><!-- 城市 -->{{this.city}}<span class="iconfont arrow-icon">&#xe65c;</span></div></router-link>

添加跳转路由后,链接内容会变成淡绿色

    .header-right// 改变跳转路径的颜色color #fff

三、Header

1. 新建’components’文件夹和’Header.vue文件(路径: src/pages/city/components/Header.vue)

<template><div>header</div>
</template><script>
export default {name: 'CityHeader'
}
</script><style lang="stylus" scoped>
</style>

2.编辑’City.vue’文件 - - - 引用’Header.vue’组件

<template><div><city-header></city-header></div>
</template><script>
import CityHeader from './components/Header'export default {name: 'City',components: {CityHeader}
}
</script><style>
</style>

3. 编写’Header.vue’样式

<template><div class="header"><!-- 返回按钮,跳转至Home页 --><router-link to="/"><span class="iconfont back-icon">&#xe743;</span></router-link>城市选择</div>
</template><script>
export default {name: 'CityHeader'
}
</script><style lang="stylus" scoped>
@import '~styles/varibles';.headerposition relativeoverflow hiddenheight $headerHightline-height $headerHightbackground $bgColorfont-size .32remtext-align centercolor #fff.back-iconposition absolutetop 0left 0width .64remfont-size .5remcolor #fff
</style>

四、Search

1. 创建’Search.vue’文件

<template><div>search</div>
</template><script>
export default {name: 'CitySearch'
}
</script><style lang="stylus" scoped>
</style>

2. 引用’Search.vue’组件 - - - 编辑’City.vue’文件

<template><div><city-header></city-header><city-search></city-search></div>
</template><script>
import CityHeader from './components/Header'
import CitySearch from './components/Search'export default {name: 'City',components: {CityHeader,CitySearch}
}
</script><style>
</style>

3. 编写’Search.vue’样式

<template><div class="search"><input class="search-input" type="text" placeholder="请输入城市名或者拼音"></div>
</template><script>
export default {name: 'CitySearch'
}
</script><style lang="stylus" scoped>
@import '~styles/varibles';.searchheight .72rembackground $bgColorpadding 0 .1rem.search-inputwidth 100%height .62remline-height .62remborder-radius .1remtext-align centercolor #666// 解决输入的文本紧贴边缘的问题box-sizing border-boxpadding 0 .1rem
</style>

五、List

1. 创建’List.vue’文件

<template>
<div>List</div>
</template><script>
export default {name: 'CityList'
}
</script><style lang="stylus" scoped>
</style>

2. 引用’List.vue’组件 - - - 编辑’City.vue’文件

<template><div><city-header></city-header><city-search></city-search><city-list></city-list></div>
</template><script>
import CityHeader from './components/Header'
import CitySearch from './components/Search'
import CityList from './components/List'export default {name: 'City',components: {CityHeader,CitySearch,CityList}
}
</script><style>
</style>

3. 编辑’List.vue’文件 - - - 实现标题

<template><div><div class="area"><div class="title border-topbottom">当前城市</div></div><div class="area"><div class="title border-topbottom">热门城市</div></div><div class="area"><div class="title border-topbottom">A</div></div></div>
</template><script>
export default {name: 'CityList'
}
</script><style lang="stylus" scoped>
@import '~styles/varibles';// 定义一个类.border-topbottom// 其中的元素&:before// 修改其中的样式border-color #ccc&:afterborder-color #ccc.area.titleline-height .54remcolor #666font-size .26rempadding-left .2rembackground #eee
</style>

4. 完善’List.vue’文件 - - - 实现城市按钮

<template><div class="list"><div><div class="area"><div class="title border-topbottom">当前城市</div><div class="button-list"><div class="button-wrapper"><div class="button">武汉</div></div></div></div><div class="area"><div class="title border-topbottom">热门城市</div><div class="button-list"><div class="button-wrapper"><div class="button">北京</div></div><div class="button-wrapper"><div class="button">上海</div></div><div class="button-wrapper"><div class="button">广州</div></div><div class="button-wrapper"><div class="button">深圳</div></div></div></div><div class="area"><div class="title border-topbottom">A</div><div class="item-list"><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div></div><div class="title border-topbottom">B</div><div class="item-list"><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div></div><div class="title border-topbottom">C</div><div class="item-list"><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div></div></div></div></div>
</template><script>
export default {name: 'CityList'
}
</script><style lang="stylus" scoped>
@import '~styles/varibles';// 定义一个类.border-topbottom// 其中的元素&:before// 修改其中的样式border-color #ccc&:afterborder-color #ccc.border-bottom&:beforeborder-color #ccc.list// 超出部分隐藏会导致页面无法滑动overflow hiddenposition absolutetop 1.58rembottom 0left 0right 0// background #000.titleline-height .54remcolor #666font-size .26rempadding-left .2rembackground #eee.button-listoverflow hiddenpadding .1rem .6rem .1rem .1rem.button-wrapperfloat leftwidth 33.33%.buttonmargin .1rempadding .1rem 0text-align centerborder .02rem solid #cccborder-radius .06rem.item-list.itempadding-left .2remline-height .7rem
</style>

4.better-scroll - - - 实现页面滑动

a. GitHub地址better-scroll

b. 安装better-scroll

npm install better-scroll -S # install 2.x,with full-featured plugin.

c. 查看GitHub文档

HTML结构:

<div class="wrapper"><ul class="content"><li>...</li><li>...</li>...</ul><!-- you can put some other DOMs here, it won't affect the scrolling
</div>

如何引用:

import BScroll from '@better-scroll/core'
let wrapper = document.querySelector('.wrapper')
let scroll = new BScroll(wrapper)

d. 完善’List.vue’文件 - - - 实现滑动效果

<template><!-- ref用来获取DOM --><div class="list" ref="wrapper"><div><div class="area"><div class="title border-topbottom">当前城市</div><div class="button-list"><div class="button-wrapper"><div class="button">武汉</div></div></div></div><div class="area"><div class="title border-topbottom">热门城市</div><div class="button-list"><div class="button-wrapper"><div class="button">北京</div></div><div class="button-wrapper"><div class="button">上海</div></div><div class="button-wrapper"><div class="button">广州</div></div><div class="button-wrapper"><div class="button">深圳</div></div></div></div><div class="area"><div class="title border-topbottom">A</div><div class="item-list"><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div></div><div class="title border-topbottom">B</div><div class="item-list"><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div></div><div class="title border-topbottom">C</div><div class="item-list"><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div><div class="item border-bottom">阿拉善</div></div></div></div></div>
</template><script>
import BetterScroll from 'better-scroll'
export default {name: 'CityList',mounted () {this.scroll = new BetterScroll(this.$refs.wrapper)},// 页面加载时,内容为空,不会超出页面高度,导致滑动失效// 生命周期函数,当页面加载完成之后,再加载scroll,实现滑动效果updated() {this.scroll.refresh()}
}
</script><style lang="stylus" scoped>
@import '~styles/varibles';// 定义一个类.border-topbottom// 其中的元素&:before// 修改其中的样式border-color #ccc&:afterborder-color #ccc.border-bottom&:beforeborder-color #ccc.list// 超出部分隐藏会导致页面无法滑动overflow hiddenposition absolutetop 1.58rembottom 0left 0right 0// background #000.titleline-height .54remcolor #666font-size .26rempadding-left .2rembackground #eee.button-listoverflow hiddenpadding .1rem .6rem .1rem .1rem.button-wrapperfloat leftwidth 33.33%.buttonmargin .1rempadding .1rem 0text-align centerborder .02rem solid #cccborder-radius .06rem.item-list.itempadding-left .2remline-height .7rem
</style>

六、Alphabet

1. 创建’Alphabet.vue’文件

<template><div>Alphabet</div>
</template><script>
export default {name: 'CityAlphabet'
}
</script><style lang="stylus" scoped>
</style>

2. 引用’Alphabet.vue’组件 - - - 编辑’City.vue’文件

<template><div><city-header></city-header><city-search></city-search><city-list></city-list><city-alphabet></city-alphabet></div>
</template><script>
import CityHeader from './components/Header'
import CitySearch from './components/Search'
import CityList from './components/List'
import CityAlphabet from './components/Alphabet'export default {name: 'City',components: {CityHeader,CitySearch,CityList,CityAlphabet}
}
</script><style>
</style>

3. 编辑’Alphabet.vue’

<template><ul class="list"><li class="item">A</li><li class="item">B</li><li class="item">C</li><li class="item">D</li><li class="item">E</li><li class="item">F</li><li class="item">G</li><li class="item">H</li></ul>
</template><script>
export default {name: 'CityAlphabet'
}
</script><style lang="stylus" scoped>
@import '~styles/varibles'.listdisplay flex// 该布局内部的子控件排列方式是纵向排列,即从上往下flex-direction column// 内容对齐属性应用在弹性容器上,把弹性项沿着弹性容器的主轴线对齐justify-content center// A不参与排列,BCD依次从顶上排列下来position absolutetop 1.58rembottom 0right 0width .4rem.itemline-height .4remtext-align centercolor $bgColor
</style>

七、Ajax

1.创建本地模拟数据 - - - 新建 'city.json’文件(路径: src/public/mock/city.json)

{"ret": true,"data":{"city": "北京","hotCities": [{"id": 1,"spell": "beijing","name": "北京"}, {"id": 3,"spell": "shanghai","name": "上海"}, {"id": 47,"spell": "xian","name": "西安"}, {"id": 239,"spell": "sanya","name": "三亚"}, {"id": 188,"spell": "lijiang","name": "丽江"}, {"id": 125,"spell": "guilin","name": "桂林"}],"cities": {"A": [{"id": 56,"spell": "aba","name": "阿坝"}, {"id": 57,"spell": "akesu","name": "阿克苏"}, {"id": 58,"spell": "alashanmeng","name": "阿拉善盟"}, {"id": 59,"spell": "aletai","name": "阿勒泰"}, {"id": 60,"spell": "ali","name": "阿里"}, {"id": 61,"spell": "ankang","name": "安康"}, {"id": 62,"spell": "anqing","name": "安庆"}, {"id": 63,"spell": "anshan","name": "鞍山"}, {"id": 64,"spell": "anshun","name": "安顺"}, {"id": 65,"spell": "anyang","name": "安阳"}, {"id": 338,"spell": "acheng","name": "阿城"}, {"id": 339,"spell": "anfu","name": "安福"}, {"id": 340,"spell": "anji","name": "安吉"}, {"id": 341,"spell": "anning","name": "安宁"}, {"id": 342,"spell": "anqiu","name": "安丘"}, {"id": 343,"spell": "anxi","name": "安溪"}, {"id": 344,"spell": "anyi","name": "安义"}, {"id": 345,"spell": "anyuan","name": "安远"}],"B": [{"id": 1,"spell": "beijing","name": "北京"}, {"id": 66,"spell": "baicheng","name": "白城"}, {"id": 67,"spell": "baise","name": "百色"}, {"id": 68,"spell": "baishan","name": "白山"}, {"id": 69,"spell": "baiyin","name": "白银"}, {"id": 70,"spell": "bangbu","name": "蚌埠"}, {"id": 71,"spell": "baoding","name": "保定"}, {"id": 72,"spell": "baoji","name": "宝鸡"}, {"id": 73,"spell": "baoshan","name": "保山"}, {"id": 74,"spell": "baotou","name": "包头"}, {"id": 75,"spell": "bayannaoer","name": "巴彦淖尔"}, {"id": 76,"spell": "bayinguoleng","name": "巴音郭楞"}, {"id": 77,"spell": "bazhong","name": "巴中"}, {"id": 78,"spell": "beihai","name": "北海"}, {"id": 79,"spell": "benxi","name": "本溪"}, {"id": 80,"spell": "bijie","name": "毕节"}, {"id": 81,"spell": "binzhou","name": "滨州"}, {"id": 82,"spell": "boertala","name": "博尔塔拉"}, {"id": 83,"spell": "bozhou","name": "亳州"}, {"id": 346,"spell": "baoying","name": "宝应"}, {"id": 347,"spell": "bayan","name": "巴彦"}, {"id": 348,"spell": "binhai","name": "滨海"}, {"id": 349,"spell": "binxian","name": "宾县"}, {"id": 350,"spell": "binyang","name": "宾阳"}, {"id": 351,"spell": "bishan","name": "璧山"}, {"id": 352,"spell": "boai","name": "博爱"}, {"id": 353,"spell": "boluo","name": "博罗"}, {"id": 354,"spell": "boxing","name": "博兴"}],"C": [{"id": 2,"spell": "chongqing","name": "重庆"}, {"id": 5,"spell": "changchun","name": "长春"}, {"id": 6,"spell": "changsha","name": "长沙"}, {"id": 7,"spell": "changzhou","name": "常州"}, {"id": 8,"spell": "chengdu","name": "成都"}, {"id": 84,"spell": "cangzhou","name": "沧州"}, {"id": 85,"spell": "changde","name": "常德"}, {"id": 86,"spell": "changdu","name": "昌都"}, {"id": 87,"spell": "changji","name": "昌吉"}, {"id": 88,"spell": "changzhi","name": "长治"}, {"id": 89,"spell": "chaohu","name": "巢湖"}, {"id": 90,"spell": "chaoyang","name": "朝阳"}, {"id": 91,"spell": "chaozhou","name": "潮州"}, {"id": 92,"spell": "chengde","name": "承德"}, {"id": 93,"spell": "chenzhou","name": "郴州"}, {"id": 94,"spell": "chifeng","name": "赤峰"}, {"id": 95,"spell": "chizhou","name": "池州"}, {"id": 96,"spell": "chongzuo","name": "崇左"}, {"id": 97,"spell": "chuxiong","name": "楚雄"}, {"id": 98,"spell": "chuzhou","name": "滁州"}, {"id": 355,"spell": "cangnan","name": "苍南"}, {"id": 356,"spell": "cangshan","name": "苍山"}, {"id": 357,"spell": "caoxian","name": "曹县"}, {"id": 358,"spell": "changdao","name": "长岛"}, {"id": 359,"spell": "changfeng","name": "长丰"}, {"id": 360,"spell": "changhai","name": "长海"}, {"id": 361,"spell": "changle","name": "长乐"}, {"id": 362,"spell": "changle","name": "昌乐"}, {"id": 363,"spell": "changshan","name": "常山"}, {"id": 364,"spell": "changshu","name": "常熟"}, {"id": 365,"spell": "changtai","name": "长泰"}, {"id": 366,"spell": "changting","name": "长汀"}, {"id": 367,"spell": "changxing","name": "长兴"}, {"id": 368,"spell": "changyi","name": "昌邑"}, {"id": 369,"spell": "chaoan","name": "潮安"}, {"id": 370,"spell": "chenggong","name": "呈贡"}, {"id": 371,"spell": "chengkou","name": "城口"}, {"id": 372,"spell": "chengwu","name": "成武"}, {"id": 373,"spell": "chiping","name": "茌平"}, {"id": 374,"spell": "chongren","name": "崇仁"}, {"id": 375,"spell": "chongyi","name": "崇义"}, {"id": 376,"spell": "chongzhou","name": "崇州"}, {"id": 377,"spell": "chunan","name": "淳安"}, {"id": 378,"spell": "cixi","name": "慈溪"}, {"id": 379,"spell": "conghua","name": "从化"}, {"id": 380,"spell": "congyang","name": "枞阳"}],"D": [{"id": 9,"spell": "dalian","name": "大连"}, {"id": 10,"spell": "dongguan","name": "东莞"}, {"id": 99,"spell": "dali","name": "大理"}, {"id": 100,"spell": "dandong","name": "丹东"}, {"id": 101,"spell": "daqing","name": "大庆"}, {"id": 102,"spell": "datong","name": "大同"}, {"id": 103,"spell": "daxinganling","name": "大兴安岭"}, {"id": 104,"spell": "dazhou","name": "达州"}, {"id": 105,"spell": "dehong","name": "德宏"}, {"id": 106,"spell": "deyang","name": "德阳"}, {"id": 107,"spell": "dezhou","name": "德州"}, {"id": 108,"spell": "dingxi","name": "定西"}, {"id": 109,"spell": "diqing","name": "迪庆"}, {"id": 110,"spell": "dongying","name": "东营"}, {"id": 381,"spell": "dafeng","name": "大丰"}, {"id": 382,"spell": "daishan","name": "岱山"}, {"id": 383,"spell": "dangshan","name": "砀山"}, {"id": 384,"spell": "dangtu","name": "当涂"}, {"id": 385,"spell": "danxian","name": "单县"}, {"id": 386,"spell": "danyang","name": "丹阳"}, {"id": 387,"spell": "dapu","name": "大埔"}, {"id": 388,"spell": "datian","name": "大田"}, {"id": 389,"spell": "dayi","name": "大邑"}, {"id": 390,"spell": "dayu","name": "大余"}, {"id": 391,"spell": "dazu","name": "大足"}, {"id": 392,"spell": "dean","name": "德安"}, {"id": 393,"spell": "dehua","name": "德化"}, {"id": 394,"spell": "dehui","name": "德惠"}, {"id": 395,"spell": "dengfeng","name": "登封"}, {"id": 396,"spell": "deqing","name": "德清"}, {"id": 397,"spell": "deqing","name": "德庆"}, {"id": 398,"spell": "dexing","name": "德兴"}, {"id": 399,"spell": "dianbai","name": "电白"}, {"id": 400,"spell": "dianjiang","name": "垫江"}, {"id": 401,"spell": "dingnan","name": "定南"}, {"id": 402,"spell": "dingtao","name": "定陶"}, {"id": 403,"spell": "dingyuan","name": "定远"}, {"id": 404,"spell": "donga","name": "东阿"}, {"id": 405,"spell": "donghai","name": "东海"}, {"id": 406,"spell": "dongming","name": "东明"}, {"id": 407,"spell": "dongping","name": "东平"}, {"id": 408,"spell": "dongshan","name": "东山"}, {"id": 409,"spell": "dongtai","name": "东台"}, {"id": 410,"spell": "dongtou","name": "洞头"}, {"id": 411,"spell": "dongxiang","name": "东乡"}, {"id": 412,"spell": "dongyang","name": "东阳"}, {"id": 413,"spell": "dongyuan","name": "东源"}, {"id": 414,"spell": "dongzhi","name": "东至"}, {"id": 415,"spell": "duchang","name": "都昌"}, {"id": 416,"spell": "dujiangyan","name": "都江堰"}],"E": [{"id": 111,"spell": "eerduosi","name": "鄂尔多斯"}, {"id": 112,"spell": "enshi","name": "恩施"}, {"id": 113,"spell": "ezhou","name": "鄂州"}, {"id": 417,"spell": "enping","name": "恩平"}],"F": [{"id": 11,"spell": "foshan","name": "佛山"}, {"id": 12,"spell": "fuzhou","name": "福州"}, {"id": 114,"spell": "fangchenggang","name": "防城港"}, {"id": 115,"spell": "fushun","name": "抚顺"}, {"id": 116,"spell": "fuxin","name": "阜新"}, {"id": 117,"spell": "fuyang","name": "阜阳"}, {"id": 118,"spell": "fuzhou","name": "抚州"}, {"id": 418,"spell": "faku","name": "法库"}, {"id": 419,"spell": "fanchang","name": "繁昌"}, {"id": 420,"spell": "fangzheng","name": "方正"}, {"id": 421,"spell": "feicheng","name": "肥城"}, {"id": 422,"spell": "feidong","name": "肥东"}, {"id": 423,"spell": "feixi","name": "肥西"}, {"id": 424,"spell": "feixian","name": "费县"}, {"id": 425,"spell": "fengcheng","name": "丰城"}, {"id": 426,"spell": "fengdu","name": "丰都"}, {"id": 427,"spell": "fenghua","name": "奉化"}, {"id": 428,"spell": "fengjie","name": "奉节"}, {"id": 429,"spell": "fengkai","name": "封开"}, {"id": 430,"spell": "fengshun","name": "丰顺"}, {"id": 431,"spell": "fengtai","name": "凤台"}, {"id": 432,"spell": "fengxian","name": "丰县"}, {"id": 433,"spell": "fengxin","name": "奉新"}, {"id": 434,"spell": "fengyang","name": "凤阳"}, {"id": 435,"spell": "fenyi","name": "分宜"}, {"id": 436,"spell": "fogang","name": "佛冈"}, {"id": 437,"spell": "fuan","name": "福安"}, {"id": 438,"spell": "fuding","name": "福鼎"}, {"id": 439,"spell": "fuliang","name": "浮梁"}, {"id": 440,"spell": "fumin","name": "富民"}, {"id": 441,"spell": "funan","name": "阜南"}, {"id": 442,"spell": "funing","name": "阜宁"}, {"id": 443,"spell": "fuqing","name": "福清"}, {"id": 444,"spell": "fuyang","name": "富阳"}],"G": [{"id": 13,"spell": "guangzhou","name": "广州"}, {"id": 14,"spell": "guiyang","name": "贵阳"}, {"id": 119,"spell": "gannan","name": "甘南"}, {"id": 120,"spell": "ganzhou","name": "赣州"}, {"id": 121,"spell": "ganzi","name": "甘孜"}, {"id": 122,"spell": "guangan","name": "广安"}, {"id": 123,"spell": "guangyuan","name": "广元"}, {"id": 124,"spell": "guigang","name": "贵港"}, {"id": 125,"spell": "guilin","name": "桂林"}, {"id": 126,"spell": "guoluo","name": "果洛"}, {"id": 127,"spell": "guyuan","name": "固原"}, {"id": 445,"spell": "ganxian","name": "赣县"}, {"id": 446,"spell": "ganyu","name": "赣榆"}, {"id": 447,"spell": "gaoan","name": "高安"}, {"id": 448,"spell": "gaocheng","name": "藁城"}, {"id": 449,"spell": "gaochun","name": "高淳"}, {"id": 450,"spell": "gaolan","name": "皋兰"}, {"id": 451,"spell": "gaoling","name": "高陵"}, {"id": 452,"spell": "gaomi","name": "高密"}, {"id": 453,"spell": "gaoqing","name": "高青"}, {"id": 454,"spell": "gaotang","name": "高唐"}, {"id": 455,"spell": "gaoyao","name": "高要"}, {"id": 456,"spell": "gaoyi","name": "高邑"}, {"id": 457,"spell": "gaoyou","name": "高邮"}, {"id": 458,"spell": "gaozhou","name": "高州"}, {"id": 459,"spell": "gongyi","name": "巩义"}, {"id": 460,"spell": "guangchang","name": "广昌"}, {"id": 461,"spell": "guangde","name": "广德"}, {"id": 462,"spell": "guangfeng","name": "广丰"}, {"id": 463,"spell": "guangning","name": "广宁"}, {"id": 464,"spell": "guangrao","name": "广饶"}, {"id": 465,"spell": "guangze","name": "光泽"}, {"id": 466,"spell": "guannan","name": "灌南"}, {"id": 467,"spell": "guanxian","name": "冠县"}, {"id": 468,"spell": "guanyun","name": "灌云"}, {"id": 469,"spell": "guixi","name": "贵溪"}, {"id": 470,"spell": "gutian","name": "古田"}, {"id": 471,"spell": "guzhen","name": "固镇"}],"H": [{"id": 15,"spell": "haerbin","name": "哈尔滨"}, {"id": 16,"spell": "haikou","name": "海口"}, {"id": 17,"spell": "handan","name": "邯郸"}, {"id": 18,"spell": "hangzhou","name": "杭州"}, {"id": 19,"spell": "hefei","name": "合肥"}, {"id": 20,"spell": "huizhou","name": "惠州"}, {"id": 128,"spell": "haibei","name": "海北"}, {"id": 129,"spell": "haidong","name": "海东"}, {"id": 130,"spell": "hainan","name": "海南"}, {"id": 131,"spell": "haixi","name": "海西"}, {"id": 132,"spell": "hami","name": "哈密"}, {"id": 133,"spell": "hanzhong","name": "汉中"}, {"id": 134,"spell": "hebi","name": "鹤壁"}, {"id": 135,"spell": "hechi","name": "河池"}, {"id": 136,"spell": "hegang","name": "鹤岗"}, {"id": 137,"spell": "heihe","name": "黑河"}, {"id": 138,"spell": "hengshui","name": "衡水"}, {"id": 139,"spell": "hengyang","name": "衡阳"}, {"id": 140,"spell": "hetiandi","name": "和田地"}, {"id": 141,"spell": "heyuan","name": "河源"}, {"id": 142,"spell": "heze","name": "菏泽"}, {"id": 143,"spell": "hezhou","name": "贺州"}, {"id": 144,"spell": "honghe","name": "红河"}, {"id": 145,"spell": "huaian","name": "淮安"}, {"id": 146,"spell": "huaibei","name": "淮北"}, {"id": 147,"spell": "huaihua","name": "怀化"}, {"id": 148,"spell": "huainan","name": "淮南"}, {"id": 149,"spell": "huanggang","name": "黄冈"}, {"id": 150,"spell": "huangnan","name": "黄南"}, {"id": 151,"spell": "huangshan","name": "黄山"}, {"id": 152,"spell": "huangshi","name": "黄石"}, {"id": 153,"spell": "huhehaote","name": "呼和浩特"}, {"id": 154,"spell": "huludao","name": "葫芦岛"}, {"id": 155,"spell": "hulunbeier","name": "呼伦贝尔"}, {"id": 156,"spell": "huzhou","name": "湖州"}, {"id": 472,"spell": "haian","name": "海安"}, {"id": 473,"spell": "haifeng","name": "海丰"}, {"id": 474,"spell": "haimen","name": "海门"}, {"id": 475,"spell": "haining","name": "海宁"}, {"id": 476,"spell": "haiyan","name": "海盐"}, {"id": 477,"spell": "haiyang","name": "海阳"}, {"id": 478,"spell": "hanshan","name": "含山"}, {"id": 479,"spell": "hechuan","name": "合川"}, {"id": 480,"spell": "hengfeng","name": "横峰"}, {"id": 481,"spell": "hengxian","name": "横县"}, {"id": 482,"spell": "heping","name": "和平"}, {"id": 483,"spell": "heshan","name": "鹤山"}, {"id": 484,"spell": "hexian","name": "和县"}, {"id": 485,"spell": "hongze","name": "洪泽"}, {"id": 486,"spell": "huaan","name": "华安"}, {"id": 487,"spell": "huadian","name": "桦甸"}, {"id": 488,"spell": "huaiji","name": "怀集"}, {"id": 489,"spell": "huaining","name": "怀宁"}, {"id": 490,"spell": "huaiyuan","name": "怀远"}, {"id": 491,"spell": "huantai","name": "桓台"}, {"id": 492,"spell": "huazhou","name": "化州"}, {"id": 493,"spell": "huian","name": "惠安"}, {"id": 494,"spell": "huichang","name": "会昌"}, {"id": 495,"spell": "huidong","name": "惠东"}, {"id": 496,"spell": "huilai","name": "惠来"}, {"id": 497,"spell": "huimin","name": "惠民"}, {"id": 498,"spell": "hukou","name": "湖口"}, {"id": 499,"spell": "hulan","name": "呼兰"}, {"id": 500,"spell": "huoqiu","name": "霍邱"}, {"id": 501,"spell": "huoshan","name": "霍山"}, {"id": 502,"spell": "huxian","name": "户县"}],"J": [{"id": 21,"spell": "jiaozuo","name": "焦作"}, {"id": 22,"spell": "jiaxing","name": "嘉兴"}, {"id": 23,"spell": "jilin","name": "吉林"}, {"id": 24,"spell": "jinan","name": "济南"}, {"id": 157,"spell": "jiamusi","name": "佳木斯"}, {"id": 158,"spell": "jiangmen","name": "江门"}, {"id": 159,"spell": "jian","name": "吉安"}, {"id": 160,"spell": "jiayuguan","name": "嘉峪关"}, {"id": 161,"spell": "jieyang","name": "揭阳"}, {"id": 162,"spell": "jinchang","name": "金昌"}, {"id": 163,"spell": "jincheng","name": "晋城"}, {"id": 164,"spell": "jingdezhen","name": "景德镇"}, {"id": 165,"spell": "jingmen","name": "荆门"}, {"id": 166,"spell": "jingzhou","name": "荆州"}, {"id": 167,"spell": "jinhua","name": "金华"}, {"id": 168,"spell": "jining","name": "济宁"}, {"id": 169,"spell": "jinzhong","name": "晋中"}, {"id": 170,"spell": "jinzhou","name": "锦州"}, {"id": 171,"spell": "jiujiang","name": "九江"}, {"id": 172,"spell": "jiuquan","name": "酒泉"}, {"id": 173,"spell": "jixi","name": "鸡西"}, {"id": 503,"spell": "jiande","name": "建德"}, {"id": 504,"spell": "jiangdu","name": "江都"}, {"id": 505,"spell": "jiangjin","name": "江津"}, {"id": 506,"spell": "jiangle","name": "将乐"}, {"id": 507,"spell": "jiangshan","name": "江山"}, {"id": 508,"spell": "jiangyan","name": "姜堰"}, {"id": 509,"spell": "jiangyin","name": "江阴"}, {"id": 510,"spell": "jianhu","name": "建湖"}, {"id": 511,"spell": "jianning","name": "建宁"}, {"id": 512,"spell": "jianou","name": "建瓯"}, {"id": 513,"spell": "jianyang","name": "建阳"}, {"id": 514,"spell": "jian","name": "吉安"}, {"id": 515,"spell": "jiaohe","name": "蛟河"}, {"id": 516,"spell": "jiaoling","name": "蕉岭"}, {"id": 517,"spell": "jiaonan","name": "胶南"}, {"id": 518,"spell": "jiaozhou","name": "胶州"}, {"id": 519,"spell": "jiashan","name": "嘉善"}, {"id": 520,"spell": "jiaxiang","name": "嘉祥"}, {"id": 521,"spell": "jiedong","name": "揭东"}, {"id": 522,"spell": "jieshou","name": "界首"}, {"id": 523,"spell": "jiexi","name": "揭西"}, {"id": 524,"spell": "jimo","name": "即墨"}, {"id": 525,"spell": "jingan","name": "靖安"}, {"id": 526,"spell": "jingde","name": "旌德"}, {"id": 527,"spell": "jinggangshan","name": "井冈山"}, {"id": 528,"spell": "jingjiang","name": "靖江"}, {"id": 529,"spell": "jingning","name": "景宁"}, {"id": 530,"spell": "jingxian","name": "泾县"}, {"id": 531,"spell": "jingxing","name": "井陉"}, {"id": 532,"spell": "jinhu","name": "金湖"}, {"id": 533,"spell": "jinjiang","name": "晋江"}, {"id": 534,"spell": "jinmen","name": "金门"}, {"id": 535,"spell": "jinning","name": "晋宁"}, {"id": 536,"spell": "jintan","name": "金坛"}, {"id": 537,"spell": "jintang","name": "金堂"}, {"id": 538,"spell": "jinxian","name": "进贤"}, {"id": 539,"spell": "jinxi","name": "金溪"}, {"id": 540,"spell": "jinxiang","name": "金乡"}, {"id": 541,"spell": "jinyun","name": "缙云"}, {"id": 542,"spell": "jinzhai","name": "金寨"}, {"id": 543,"spell": "jinzhou","name": "晋州"}, {"id": 544,"spell": "jishui","name": "吉水"}, {"id": 545,"spell": "jiujiang","name": "九江"}, {"id": 546,"spell": "jiutai","name": "九台"}, {"id": 547,"spell": "jixi","name": "绩溪"}, {"id": 548,"spell": "jiyang","name": "济阳"}, {"id": 549,"spell": "jiyuan","name": "济源"}, {"id": 550,"spell": "juancheng","name": "鄄城"}, {"id": 551,"spell": "junan","name": "莒南"}, {"id": 552,"spell": "jurong","name": "句容"}, {"id": 553,"spell": "juxian","name": "莒县"}, {"id": 554,"spell": "juye","name": "巨野"}],"K": [{"id": 25,"spell": "kunming","name": "昆明"}, {"id": 174,"spell": "kaifeng","name": "开封"}, {"id": 175,"spell": "kashidi","name": "喀什地"}, {"id": 176,"spell": "kelamayi","name": "克拉玛依"}, {"id": 177,"spell": "kezile","name": "克孜勒"}, {"id": 555,"spell": "kaihua","name": "开化"}, {"id": 556,"spell": "kaiping","name": "开平"}, {"id": 557,"spell": "kaixian","name": "开县"}, {"id": 558,"spell": "kaiyang","name": "开阳"}, {"id": 559,"spell": "kangping","name": "康平"}, {"id": 560,"spell": "kenli","name": "垦利"}, {"id": 561,"spell": "kunshan","name": "昆山"}],"L": [{"id": 26,"spell": "lanzhou","name": "兰州"}, {"id": 27,"spell": "liuzhou","name": "柳州"}, {"id": 28,"spell": "luoyang","name": "洛阳"}, {"id": 178,"spell": "laibin","name": "来宾"}, {"id": 179,"spell": "laiwu","name": "莱芜"}, {"id": 180,"spell": "langfang","name": "廊坊"}, {"id": 181,"spell": "lasa","name": "拉萨"}, {"id": 182,"spell": "leshan","name": "乐山"}, {"id": 183,"spell": "liangshan","name": "凉山"}, {"id": 184,"spell": "lianyungang","name": "连云港"}, {"id": 185,"spell": "liaocheng","name": "聊城"}, {"id": 186,"spell": "liaoyang","name": "辽阳"}, {"id": 187,"spell": "liaoyuan","name": "辽源"}, {"id": 188,"spell": "lijiang","name": "丽江"}, {"id": 189,"spell": "lincang","name": "临沧"}, {"id": 190,"spell": "linfen","name": "临汾"}, {"id": 191,"spell": "linxia","name": "临夏"}, {"id": 192,"spell": "linyi","name": "临沂"}, {"id": 193,"spell": "linzhi","name": "林芝"}, {"id": 194,"spell": "lishui","name": "丽水"}, {"id": 195,"spell": "liuan","name": "六安"}, {"id": 196,"spell": "liupanshui","name": "六盘水"}, {"id": 197,"spell": "longnan","name": "陇南"}, {"id": 198,"spell": "longyan","name": "龙岩"}, {"id": 199,"spell": "loudi","name": "娄底"}, {"id": 200,"spell": "luohe","name": "漯河"}, {"id": 201,"spell": "luzhou","name": "泸州"}, {"id": 202,"spell": "lvliang","name": "吕梁"}, {"id": 562,"spell": "laian","name": "来安"}, {"id": 563,"spell": "laixi","name": "莱西"}, {"id": 564,"spell": "laiyang","name": "莱阳"}, {"id": 565,"spell": "laizhou","name": "莱州"}, {"id": 566,"spell": "langxi","name": "郎溪"}, {"id": 567,"spell": "lantian","name": "蓝田"}, {"id": 568,"spell": "lanxi","name": "兰溪"}, {"id": 569,"spell": "lean","name": "乐安"}, {"id": 570,"spell": "lechang","name": "乐昌"}, {"id": 571,"spell": "leizhou","name": "雷州"}, {"id": 572,"spell": "leling","name": "乐陵"}, {"id": 573,"spell": "leping","name": "乐平"}, {"id": 574,"spell": "leqing","name": "乐清"}, {"id": 575,"spell": "leting","name": "乐亭"}, {"id": 576,"spell": "liancheng","name": "连城"}, {"id": 577,"spell": "liangping","name": "梁平"}, {"id": 578,"spell": "liangshan","name": "梁山"}, {"id": 579,"spell": "lianhua","name": "莲花"}, {"id": 580,"spell": "lianjiang","name": "连江"}, {"id": 581,"spell": "lianjiang","name": "廉江"}, {"id": 582,"spell": "liannan","name": "连南"}, {"id": 583,"spell": "lianping","name": "连平"}, {"id": 584,"spell": "lianshan","name": "连山"}, {"id": 585,"spell": "lianshui","name": "涟水"}, {"id": 586,"spell": "lianzhou","name": "连州"}, {"id": 587,"spell": "liaozhong","name": "辽中"}, {"id": 588,"spell": "lichuan","name": "黎川"}, {"id": 589,"spell": "lijin","name": "利津"}, {"id": 590,"spell": "linan","name": "临安"}, {"id": 591,"spell": "lingbi","name": "灵璧"}, {"id": 592,"spell": "lingshou","name": "灵寿"}, {"id": 593,"spell": "lingxian","name": "陵县"}, {"id": 594,"spell": "linhai","name": "临海"}, {"id": 595,"spell": "linqing","name": "临清"}, {"id": 596,"spell": "linquan","name": "临泉"}, {"id": 597,"spell": "linqu","name": "临朐"}, {"id": 598,"spell": "linshu","name": "临沭"}, {"id": 599,"spell": "linyi","name": "临邑"}, {"id": 600,"spell": "lishui","name": "溧水"}, {"id": 601,"spell": "liucheng","name": "柳城"}, {"id": 602,"spell": "liujiang","name": "柳江"}, {"id": 603,"spell": "liuyang","name": "浏阳"}, {"id": 604,"spell": "lixin","name": "利辛"}, {"id": 605,"spell": "liyang","name": "溧阳"}, {"id": 606,"spell": "longan","name": "隆安"}, {"id": 607,"spell": "longchuan","name": "龙川"}, {"id": 608,"spell": "longhai","name": "龙海"}, {"id": 609,"spell": "longkou","name": "龙口"}, {"id": 610,"spell": "longmen","name": "龙门"}, {"id": 611,"spell": "longnan","name": "龙南"}, {"id": 612,"spell": "longquan","name": "龙泉"}, {"id": 613,"spell": "longyou","name": "龙游"}, {"id": 614,"spell": "luancheng","name": "栾城"}, {"id": 615,"spell": "luanchuan","name": "栾川"}, {"id": 616,"spell": "luannan","name": "滦南"}, {"id": 617,"spell": "luanxian","name": "滦县"}, {"id": 618,"spell": "lufeng","name": "陆丰"}, {"id": 619,"spell": "luhe","name": "陆河"}, {"id": 620,"spell": "lujiang","name": "庐江"}, {"id": 621,"spell": "luoding","name": "罗定"}, {"id": 622,"spell": "luoning","name": "洛宁"}, {"id": 623,"spell": "luoyuan","name": "罗源"}, {"id": 624,"spell": "luquan","name": "鹿泉"}, {"id": 625,"spell": "luquan","name": "禄劝"}, {"id": 626,"spell": "luxi","name": "芦溪"}, {"id": 627,"spell": "luzhai","name": "鹿寨"}],"M": [{"id": 203,"spell": "maanshan","name": "马鞍山"}, {"id": 204,"spell": "maoming","name": "茂名"}, {"id": 205,"spell": "meishan","name": "眉山"}, {"id": 206,"spell": "meizhou","name": "梅州"}, {"id": 207,"spell": "mianyang","name": "绵阳"}, {"id": 208,"spell": "mudanjiang","name": "牡丹江"}, {"id": 628,"spell": "mashan","name": "马山"}, {"id": 629,"spell": "meixian","name": "梅县"}, {"id": 630,"spell": "mengcheng","name": "蒙城"}, {"id": 631,"spell": "mengjin","name": "孟津"}, {"id": 632,"spell": "mengyin","name": "蒙阴"}, {"id": 633,"spell": "mengzhou","name": "孟州"}, {"id": 634,"spell": "mingguang","name": "明光"}, {"id": 635,"spell": "mingxi","name": "明溪"}, {"id": 636,"spell": "minhou","name": "闽侯"}, {"id": 637,"spell": "minqing","name": "闽清"}, {"id": 638,"spell": "mulan","name": "木兰"}],"N": [{"id": 29,"spell": "nanchang","name": "南昌"}, {"id": 30,"spell": "nanjing","name": "南京"}, {"id": 31,"spell": "nanning","name": "南宁"}, {"id": 32,"spell": "nantong","name": "南通"}, {"id": 33,"spell": "ningbo","name": "宁波"}, {"id": 209,"spell": "nanchong","name": "南充"}, {"id": 210,"spell": "nanping","name": "南平"}, {"id": 211,"spell": "nanyang","name": "南阳"}, {"id": 212,"spell": "naqu","name": "那曲"}, {"id": 213,"spell": "neijiang","name": "内江"}, {"id": 214,"spell": "ningde","name": "宁德"}, {"id": 215,"spell": "nujiang","name": "怒江"}, {"id": 639,"spell": "nanan","name": "南安"}, {"id": 640,"spell": "nanao","name": "南澳"}, {"id": 641,"spell": "nancheng","name": "南城"}, {"id": 642,"spell": "nanchuan","name": "南川"}, {"id": 643,"spell": "nanfeng","name": "南丰"}, {"id": 644,"spell": "nanjing","name": "南靖"}, {"id": 645,"spell": "nankang","name": "南康"}, {"id": 646,"spell": "nanling","name": "南陵"}, {"id": 647,"spell": "nanxiong","name": "南雄"}, {"id": 648,"spell": "ningdu","name": "宁都"}, {"id": 649,"spell": "ningguo","name": "宁国"}, {"id": 650,"spell": "ninghai","name": "宁海"}, {"id": 651,"spell": "ninghua","name": "宁化"}, {"id": 652,"spell": "ningjin","name": "宁津"}, {"id": 653,"spell": "ningxiang","name": "宁乡"}, {"id": 654,"spell": "ningyang","name": "宁阳"}, {"id": 655,"spell": "nongan","name": "农安"}],"P": [{"id": 216,"spell": "panjin","name": "盘锦"}, {"id": 217,"spell": "panzhihua","name": "攀枝花"}, {"id": 218,"spell": "pingdingshan","name": "平顶山"}, {"id": 219,"spell": "pingliang","name": "平凉"}, {"id": 220,"spell": "pingxiang","name": "萍乡"}, {"id": 221,"spell": "puer","name": "普洱"}, {"id": 222,"spell": "putian","name": "莆田"}, {"id": 223,"spell": "puyang","name": "濮阳"}, {"id": 656,"spell": "panan","name": "磐安"}, {"id": 657,"spell": "panshi","name": "磐石"}, {"id": 658,"spell": "peixian","name": "沛县"}, {"id": 659,"spell": "penglai","name": "蓬莱"}, {"id": 660,"spell": "pengshui","name": "彭水"}, {"id": 661,"spell": "pengze","name": "彭泽"}, {"id": 662,"spell": "pengzhou","name": "彭州"}, {"id": 663,"spell": "pingdu","name": "平度"}, {"id": 664,"spell": "pinghe","name": "平和"}, {"id": 665,"spell": "pinghu","name": "平湖"}, {"id": 666,"spell": "pingnan","name": "屏南"}, {"id": 667,"spell": "pingshan","name": "平山"}, {"id": 668,"spell": "pingtan","name": "平潭"}, {"id": 669,"spell": "pingyang","name": "平阳"}, {"id": 670,"spell": "pingyin","name": "平阴"}, {"id": 671,"spell": "pingyi","name": "平邑"}, {"id": 672,"spell": "pingyuan","name": "平原"}, {"id": 673,"spell": "pingyuan","name": "平远"}, {"id": 674,"spell": "pixian","name": "郫县"}, {"id": 675,"spell": "pizhou","name": "邳州"}, {"id": 676,"spell": "poyang","name": "鄱阳"}, {"id": 677,"spell": "pucheng","name": "浦城"}, {"id": 678,"spell": "pujiang","name": "浦江"}, {"id": 679,"spell": "pujiang","name": "蒲江"}, {"id": 680,"spell": "pulandian","name": "普兰店"}, {"id": 681,"spell": "puning","name": "普宁"}],"Q": [{"id": 34,"spell": "qingdao","name": "青岛"}, {"id": 35,"spell": "quanzhou","name": "泉州"}, {"id": 224,"spell": "qiandong","name": "黔东"}, {"id": 225,"spell": "qiannan","name": "黔南"}, {"id": 226,"spell": "qianxinan","name": "黔西南"}, {"id": 227,"spell": "qingyang","name": "庆阳"}, {"id": 228,"spell": "qingyuan","name": "清远"}, {"id": 229,"spell": "qinhuangdao","name": "秦皇岛"}, {"id": 230,"spell": "qinzhou","name": "钦州"}, {"id": 231,"spell": "qiqihaer","name": "齐齐哈尔"}, {"id": 232,"spell": "qitaihe","name": "七台河"}, {"id": 233,"spell": "qujing","name": "曲靖"}, {"id": 234,"spell": "quzhou","name": "衢州"}, {"id": 682,"spell": "qianan","name": "迁安"}, {"id": 683,"spell": "qianshan","name": "潜山"}, {"id": 684,"spell": "qianshan","name": "铅山"}, {"id": 685,"spell": "qianxi","name": "迁西"}, {"id": 686,"spell": "qidong","name": "启东"}, {"id": 687,"spell": "qihe","name": "齐河"}, {"id": 688,"spell": "qijiang","name": "綦江"}, {"id": 689,"spell": "qimen","name": "祁门"}, {"id": 690,"spell": "qingliu","name": "清流"}, {"id": 691,"spell": "qingtian","name": "青田"}, {"id": 692,"spell": "qingxin","name": "清新"}, {"id": 693,"spell": "qingyang","name": "青阳"}, {"id": 694,"spell": "qingyuan","name": "庆元"}, {"id": 695,"spell": "qingyun","name": "庆云"}, {"id": 696,"spell": "qingzhen","name": "清镇"}, {"id": 697,"spell": "qingzhou","name": "青州"}, {"id": 698,"spell": "qinyang","name": "沁阳"}, {"id": 699,"spell": "qionglai","name": "邛崃"}, {"id": 700,"spell": "qixia","name": "栖霞"}, {"id": 701,"spell": "quanjiao","name": "全椒"}, {"id": 702,"spell": "quannan","name": "全南"}, {"id": 703,"spell": "qufu","name": "曲阜"}, {"id": 704,"spell": "qujiang","name": "曲江"}],"R": [{"id": 235,"spell": "rikaze","name": "日喀则"}, {"id": 236,"spell": "rizhao","name": "日照"}, {"id": 705,"spell": "raoping","name": "饶平"}, {"id": 706,"spell": "renhua","name": "仁化"}, {"id": 707,"spell": "rongan","name": "融安"}, {"id": 708,"spell": "rongchang","name": "荣昌"}, {"id": 709,"spell": "rongcheng","name": "荣成"}, {"id": 710,"spell": "rongshui","name": "融水"}, {"id": 711,"spell": "rudong","name": "如东"}, {"id": 712,"spell": "rugao","name": "如皋"}, {"id": 713,"spell": "ruian","name": "瑞安"}, {"id": 714,"spell": "ruichang","name": "瑞昌"}, {"id": 715,"spell": "ruijin","name": "瑞金"}, {"id": 716,"spell": "rushan","name": "乳山"}, {"id": 717,"spell": "ruyang","name": "汝阳"}, {"id": 718,"spell": "ruyuan","name": "乳源"}],"S": [{"id": 3,"spell": "shanghai","name": "上海"}, {"id": 36,"spell": "shenyang","name": "沈阳"}, {"id": 37,"spell": "shenzhen","name": "深圳"}, {"id": 38,"spell": "shijiazhuang","name": "石家庄"}, {"id": 39,"spell": "suzhou","name": "苏州"}, {"id": 237,"spell": "sanmenxia","name": "三门峡"}, {"id": 238,"spell": "sanming","name": "三明"}, {"id": 239,"spell": "sanya","name": "三亚"}, {"id": 240,"spell": "shangluo","name": "商洛"}, {"id": 241,"spell": "shangqiu","name": "商丘"}, {"id": 242,"spell": "shangrao","name": "上饶"}, {"id": 243,"spell": "shannan","name": "山南"}, {"id": 244,"spell": "shantou","name": "汕头"}, {"id": 245,"spell": "shanwei","name": "汕尾"}, {"id": 246,"spell": "shaoguan","name": "韶关"}, {"id": 247,"spell": "shaoxing","name": "绍兴"}, {"id": 248,"spell": "shaoyang","name": "邵阳"}, {"id": 249,"spell": "shiyan","name": "十堰"}, {"id": 250,"spell": "shizuishan","name": "石嘴山"}, {"id": 251,"spell": "shuangyashan","name": "双鸭山"}, {"id": 252,"spell": "shuozhou","name": "朔州"}, {"id": 253,"spell": "siping","name": "四平"}, {"id": 254,"spell": "songyuan","name": "松原"}, {"id": 255,"spell": "suihua","name": "绥化"}, {"id": 256,"spell": "suining","name": "遂宁"}, {"id": 257,"spell": "suizhou","name": "随州"}, {"id": 258,"spell": "suqian","name": "宿迁"}, {"id": 259,"spell": "suzhou","name": "宿州"}, {"id": 719,"spell": "sanjiang","name": "三江"}, {"id": 720,"spell": "sanmen","name": "三门"}, {"id": 721,"spell": "saoan","name": "诏安"}, {"id": 722,"spell": "shanggao","name": "上高"}, {"id": 723,"spell": "shanghang","name": "上杭"}, {"id": 724,"spell": "shanghe","name": "商河"}, {"id": 725,"spell": "shangli","name": "上栗"}, {"id": 726,"spell": "shanglin","name": "上林"}, {"id": 727,"spell": "shangrao","name": "上饶"}, {"id": 728,"spell": "shangyou","name": "上犹"}, {"id": 729,"spell": "shangyu","name": "上虞"}, {"id": 730,"spell": "shangzhi","name": "尚志"}, {"id": 731,"spell": "shaowu","name": "邵武"}, {"id": 732,"spell": "shaoxing","name": "绍兴"}, {"id": 733,"spell": "shaxian","name": "沙县"}, {"id": 734,"spell": "shengsi","name": "嵊泗"}, {"id": 735,"spell": "shengzhou","name": "嵊州"}, {"id": 736,"spell": "shenxian","name": "莘县"}, {"id": 737,"spell": "shenze","name": "深泽"}, {"id": 738,"spell": "shexian","name": "歙县"}, {"id": 739,"spell": "sheyang","name": "射阳"}, {"id": 740,"spell": "shicheng","name": "石城"}, {"id": 741,"spell": "shilin","name": "石林"}, {"id": 742,"spell": "shishi","name": "石狮"}, {"id": 743,"spell": "shitai","name": "石台"}, {"id": 744,"spell": "shixing","name": "始兴"}, {"id": 745,"spell": "shizhu","name": "石柱"}, {"id": 746,"spell": "shouguang","name": "寿光"}, {"id": 747,"spell": "shouning","name": "寿宁"}, {"id": 748,"spell": "shouxian","name": "寿县"}, {"id": 749,"spell": "shuangcheng","name": "双城"}, {"id": 750,"spell": "shuangliu","name": "双流"}, {"id": 751,"spell": "shucheng","name": "舒城"}, {"id": 752,"spell": "shulan","name": "舒兰"}, {"id": 753,"spell": "shunchang","name": "顺昌"}, {"id": 754,"spell": "shuyang","name": "沭阳"}, {"id": 755,"spell": "sihong","name": "泗洪"}, {"id": 756,"spell": "sihui","name": "四会"}, {"id": 757,"spell": "sishui","name": "泗水"}, {"id": 758,"spell": "sixian","name": "泗县"}, {"id": 759,"spell": "siyang","name": "泗阳"}, {"id": 760,"spell": "songming","name": "嵩明"}, {"id": 761,"spell": "songxi","name": "松溪"}, {"id": 762,"spell": "songxian","name": "嵩县"}, {"id": 763,"spell": "songyang","name": "松阳"}, {"id": 764,"spell": "suichang","name": "遂昌"}, {"id": 765,"spell": "suichuan","name": "遂川"}, {"id": 766,"spell": "suining","name": "睢宁"}, {"id": 767,"spell": "suixi","name": "濉溪"}, {"id": 768,"spell": "suixi","name": "遂溪"}, {"id": 769,"spell": "susong","name": "宿松"}, {"id": 770,"spell": "suyu","name": "宿豫"}],"T": [{"id": 4,"spell": "tianjin","name": "天津"}, {"id": 40,"spell": "taizhou","name": "台州"}, {"id": 41,"spell": "tangshan","name": "唐山"}, {"id": 260,"spell": "tachengdi","name": "塔城地"}, {"id": 261,"spell": "taian","name": "泰安"}, {"id": 262,"spell": "taiyuan","name": "太原"}, {"id": 263,"spell": "taizhou","name": "泰州"}, {"id": 264,"spell": "tianshui","name": "天水"}, {"id": 265,"spell": "tieling","name": "铁岭"}, {"id": 266,"spell": "tongchuan","name": "铜川"}, {"id": 267,"spell": "tonghua","name": "通化"}, {"id": 268,"spell": "tongliao","name": "通辽"}, {"id": 269,"spell": "tongling","name": "铜陵"}, {"id": 270,"spell": "tongren","name": "铜仁"}, {"id": 271,"spell": "tulufan","name": "吐鲁番"}, {"id": 771,"spell": "taicang","name": "太仓"}, {"id": 772,"spell": "taihe","name": "太和"}, {"id": 773,"spell": "taihe","name": "泰和"}, {"id": 774,"spell": "taihu","name": "太湖"}, {"id": 775,"spell": "taining","name": "泰宁"}, {"id": 776,"spell": "taishan","name": "台山"}, {"id": 777,"spell": "taishun","name": "泰顺"}, {"id": 778,"spell": "taixing","name": "泰兴"}, {"id": 779,"spell": "tancheng","name": "郯城"}, {"id": 780,"spell": "tanghai","name": "唐海"}, {"id": 781,"spell": "tengzhou","name": "滕州"}, {"id": 782,"spell": "tianchang","name": "天长"}, {"id": 783,"spell": "tiantai","name": "天台"}, {"id": 784,"spell": "tongcheng","name": "桐城"}, {"id": 785,"spell": "tonggu","name": "铜鼓"}, {"id": 786,"spell": "tonghe","name": "通河"}, {"id": 787,"spell": "tongliang","name": "铜梁"}, {"id": 788,"spell": "tongling","name": "铜陵"}, {"id": 789,"spell": "tonglu","name": "桐庐"}, {"id": 790,"spell": "tongnan","name": "潼南"}, {"id": 791,"spell": "tongshan","name": "铜山"}, {"id": 792,"spell": "tongxiang","name": "桐乡"}, {"id": 793,"spell": "tongzhou","name": "通州"}],"W": [{"id": 42,"spell": "weifang","name": "潍坊"}, {"id": 43,"spell": "weihai","name": "威海"}, {"id": 44,"spell": "wuhan","name": "武汉"}, {"id": 45,"spell": "wuxi","name": "无锡"}, {"id": 272,"spell": "weinan","name": "渭南"}, {"id": 273,"spell": "wenshan","name": "文山"}, {"id": 274,"spell": "wenzhou","name": "温州"}, {"id": 275,"spell": "wuhai","name": "乌海"}, {"id": 276,"spell": "wuhu","name": "芜湖"}, {"id": 277,"spell": "wulanchabu","name": "乌兰察布"}, {"id": 278,"spell": "wulumuqi","name": "乌鲁木齐"}, {"id": 279,"spell": "wuwei","name": "武威"}, {"id": 280,"spell": "wuzhong","name": "吴忠"}, {"id": 281,"spell": "wuzhou","name": "梧州"}, {"id": 794,"spell": "wafangdian","name": "瓦房店"}, {"id": 795,"spell": "wanan","name": "万安"}, {"id": 796,"spell": "wangcheng","name": "望城"}, {"id": 797,"spell": "wangjiang","name": "望江"}, {"id": 798,"spell": "wannian","name": "万年"}, {"id": 799,"spell": "wanzai","name": "万载"}, {"id": 800,"spell": "weishan","name": "微山"}, {"id": 801,"spell": "wencheng","name": "文成"}, {"id": 802,"spell": "wendeng","name": "文登"}, {"id": 803,"spell": "wengyuan","name": "翁源"}, {"id": 804,"spell": "wenling","name": "温岭"}, {"id": 805,"spell": "wenshang","name": "汶上"}, {"id": 806,"spell": "wenxian","name": "温县"}, {"id": 807,"spell": "woyang","name": "涡阳"}, {"id": 808,"spell": "wuchang","name": "五常"}, {"id": 809,"spell": "wucheng","name": "武城"}, {"id": 810,"spell": "wuchuan","name": "吴川"}, {"id": 811,"spell": "wudi","name": "无棣"}, {"id": 812,"spell": "wuhe","name": "五河"}, {"id": 813,"spell": "wuhu","name": "芜湖"}, {"id": 814,"spell": "wuhua","name": "五华"}, {"id": 815,"spell": "wuji","name": "无极"}, {"id": 816,"spell": "wujiang","name": "吴江"}, {"id": 817,"spell": "wulian","name": "五莲"}, {"id": 818,"spell": "wulong","name": "武隆"}, {"id": 819,"spell": "wuming","name": "武鸣"}, {"id": 820,"spell": "wuning","name": "武宁"}, {"id": 821,"spell": "wuping","name": "武平"}, {"id": 822,"spell": "wushan","name": "巫山"}, {"id": 823,"spell": "wuwei","name": "无为"}, {"id": 824,"spell": "wuxi","name": "巫溪"}, {"id": 825,"spell": "wuyi","name": "武义"}, {"id": 826,"spell": "wuyishan","name": "武夷山"}, {"id": 827,"spell": "wuyuan","name": "婺源"}, {"id": 828,"spell": "wuzhi","name": "武陟"}],"X": [{"id": 46,"spell": "xiamen","name": "厦门"}, {"id": 47,"spell": "xian","name": "西安"}, {"id": 48,"spell": "xuchang","name": "许昌"}, {"id": 49,"spell": "xuzhou","name": "徐州"}, {"id": 282,"spell": "xiangfan","name": "襄樊"}, {"id": 283,"spell": "xiangtan","name": "湘潭"}, {"id": 284,"spell": "xiangxi","name": "湘西"}, {"id": 285,"spell": "xianning","name": "咸宁"}, {"id": 286,"spell": "xianyang","name": "咸阳"}, {"id": 287,"spell": "xiaogan","name": "孝感"}, {"id": 288,"spell": "xilinguolemeng","name": "锡林郭勒盟"}, {"id": 289,"spell": "xinganmeng","name": "兴安盟"}, {"id": 290,"spell": "xingtai","name": "邢台"}, {"id": 291,"spell": "xining","name": "西宁"}, {"id": 292,"spell": "xinxiang","name": "新乡"}, {"id": 293,"spell": "xinyang","name": "信阳"}, {"id": 294,"spell": "xinyu","name": "新余"}, {"id": 295,"spell": "xinzhou","name": "忻州"}, {"id": 296,"spell": "xishuangbanna","name": "西双版纳"}, {"id": 297,"spell": "xuancheng","name": "宣城"}, {"id": 829,"spell": "xiajiang","name": "峡江"}, {"id": 830,"spell": "xiajin","name": "夏津"}, {"id": 831,"spell": "xiangshan","name": "象山"}, {"id": 832,"spell": "xiangshui","name": "响水"}, {"id": 833,"spell": "xianju","name": "仙居"}, {"id": 834,"spell": "xianyou","name": "仙游"}, {"id": 835,"spell": "xiaoxian","name": "萧县"}, {"id": 836,"spell": "xiapu","name": "霞浦"}, {"id": 837,"spell": "xifeng","name": "息烽"}, {"id": 838,"spell": "xinan","name": "新安"}, {"id": 839,"spell": "xinchang","name": "新昌"}, {"id": 840,"spell": "xinfeng","name": "信丰"}, {"id": 841,"spell": "xinfeng","name": "新丰"}, {"id": 842,"spell": "xingan","name": "新干"}, {"id": 843,"spell": "xingguo","name": "兴国"}, {"id": 844,"spell": "xinghua","name": "兴化"}, {"id": 845,"spell": "xingning","name": "兴宁"}, {"id": 846,"spell": "xingtang","name": "行唐"}, {"id": 847,"spell": "xingyang","name": "荥阳"}, {"id": 848,"spell": "xingzi","name": "星子"}, {"id": 849,"spell": "xinji","name": "辛集"}, {"id": 850,"spell": "xinjian","name": "新建"}, {"id": 851,"spell": "xinjin","name": "新津"}, {"id": 852,"spell": "xinle","name": "新乐"}, {"id": 853,"spell": "xinmin","name": "新民"}, {"id": 854,"spell": "xinmi","name": "新密"}, {"id": 855,"spell": "xintai","name": "新泰"}, {"id": 856,"spell": "xinxing","name": "新兴"}, {"id": 857,"spell": "xinyi","name": "新沂"}, {"id": 858,"spell": "xinyi","name": "信宜"}, {"id": 859,"spell": "xinzheng","name": "新郑"}, {"id": 860,"spell": "xiuning","name": "休宁"}, {"id": 861,"spell": "xiushan","name": "秀山"}, {"id": 862,"spell": "xiushui","name": "修水"}, {"id": 863,"spell": "xiuwen","name": "修文"}, {"id": 864,"spell": "xiuwu","name": "修武"}, {"id": 865,"spell": "xundian","name": "寻甸"}, {"id": 866,"spell": "xunwu","name": "寻乌"}, {"id": 867,"spell": "xuwen","name": "徐闻"}, {"id": 868,"spell": "xuyi","name": "盱眙"}],"Y": [{"id": 50,"spell": "yangzhou","name": "扬州"}, {"id": 51,"spell": "yantai","name": "烟台"}, {"id": 298,"spell": "yaan","name": "雅安"}, {"id": 299,"spell": "yanan","name": "延安"}, {"id": 300,"spell": "yanbian","name": "延边"}, {"id": 301,"spell": "yancheng","name": "盐城"}, {"id": 302,"spell": "yangjiang","name": "阳江"}, {"id": 303,"spell": "yangquan","name": "阳泉"}, {"id": 304,"spell": "yibin","name": "宜宾"}, {"id": 305,"spell": "yichang","name": "宜昌"}, {"id": 306,"spell": "yichun","name": "伊春"}, {"id": 307,"spell": "yichun","name": "宜春"}, {"id": 308,"spell": "yilihasake","name": "伊犁哈萨克"}, {"id": 309,"spell": "yinchuan","name": "银川"}, {"id": 310,"spell": "yingkou","name": "营口"}, {"id": 311,"spell": "yingtan","name": "鹰潭"}, {"id": 312,"spell": "yiyang","name": "益阳"}, {"id": 313,"spell": "yongzhou","name": "永州"}, {"id": 314,"spell": "yueyang","name": "岳阳"}, {"id": 315,"spell": "yulin","name": "玉林"}, {"id": 316,"spell": "yulin","name": "榆林"}, {"id": 317,"spell": "yuncheng","name": "运城"}, {"id": 318,"spell": "yunfu","name": "云浮"}, {"id": 319,"spell": "yushu","name": "玉树"}, {"id": 320,"spell": "yuxi","name": "玉溪"}, {"id": 869,"spell": "yangchun","name": "阳春"}, {"id": 870,"spell": "yangdong","name": "阳东"}, {"id": 871,"spell": "yanggu","name": "阳谷"}, {"id": 872,"spell": "yangshan","name": "阳山"}, {"id": 873,"spell": "yangxin","name": "阳信"}, {"id": 874,"spell": "yangxi","name": "阳西"}, {"id": 875,"spell": "yangzhong","name": "扬中"}, {"id": 876,"spell": "yanshi","name": "偃师"}, {"id": 877,"spell": "yanshou","name": "延寿"}, {"id": 878,"spell": "yanzhou","name": "兖州"}, {"id": 879,"spell": "yichuan","name": "伊川"}, {"id": 880,"spell": "yifeng","name": "宜丰"}, {"id": 881,"spell": "yihuang","name": "宜黄"}, {"id": 882,"spell": "yilan","name": "依兰"}, {"id": 883,"spell": "yiliang","name": "宜良"}, {"id": 884,"spell": "yinan","name": "沂南"}, {"id": 885,"spell": "yingde","name": "英德"}, {"id": 886,"spell": "yingshang","name": "颍上"}, {"id": 887,"spell": "yishui","name": "沂水"}, {"id": 888,"spell": "yiwu","name": "义乌"}, {"id": 889,"spell": "yixian","name": "黟县"}, {"id": 890,"spell": "yixing","name": "宜兴"}, {"id": 891,"spell": "yiyang","name": "弋阳"}, {"id": 892,"spell": "yiyang","name": "宜阳"}, {"id": 893,"spell": "yiyuan","name": "沂源"}, {"id": 894,"spell": "yizheng","name": "仪征"}, {"id": 895,"spell": "yongan","name": "永安"}, {"id": 896,"spell": "yongchuan","name": "永川"}, {"id": 897,"spell": "yongchun","name": "永春"}, {"id": 898,"spell": "yongdeng","name": "永登"}, {"id": 899,"spell": "yongding","name": "永定"}, {"id": 900,"spell": "yongfeng","name": "永丰"}, {"id": 901,"spell": "yongji","name": "永吉"}, {"id": 902,"spell": "yongjia","name": "永嘉"}, {"id": 903,"spell": "yongkang","name": "永康"}, {"id": 904,"spell": "yongning","name": "邕宁"}, {"id": 905,"spell": "yongtai","name": "永泰"}, {"id": 906,"spell": "yongxin","name": "永新"}, {"id": 907,"spell": "yongxiu","name": "永修"}, {"id": 908,"spell": "youxi","name": "尤溪"}, {"id": 909,"spell": "youyang","name": "酉阳"}, {"id": 910,"spell": "yuanshi","name": "元氏"}, {"id": 911,"spell": "yucheng","name": "禹城"}, {"id": 912,"spell": "yudu","name": "于都"}, {"id": 913,"spell": "yuexi","name": "岳西"}, {"id": 914,"spell": "yugan","name": "余干"}, {"id": 915,"spell": "yuhuan","name": "玉环"}, {"id": 916,"spell": "yujiang","name": "余江"}, {"id": 917,"spell": "yunan","name": "郁南"}, {"id": 918,"spell": "yunan","name": "云安"}, {"id": 919,"spell": "yuncheng","name": "郓城"}, {"id": 920,"spell": "yunhe","name": "云和"}, {"id": 921,"spell": "yunxiao","name": "云霄"}, {"id": 922,"spell": "yunyang","name": "云阳"}, {"id": 923,"spell": "yushan","name": "玉山"}, {"id": 924,"spell": "yushu","name": "榆树"}, {"id": 925,"spell": "yutai","name": "鱼台"}, {"id": 926,"spell": "yutian","name": "玉田"}, {"id": 927,"spell": "yuyao","name": "余姚"}, {"id": 928,"spell": "yuzhong","name": "榆中"}],"Z": [{"id": 52,"spell": "zhangzhou","name": "漳州"}, {"id": 53,"spell": "zhengzhou","name": "郑州"}, {"id": 54,"spell": "zhongshan","name": "中山"}, {"id": 55,"spell": "zhuhai","name": "珠海"}, {"id": 321,"spell": "zaozhuang","name": "枣庄"}, {"id": 322,"spell": "zhangjiajie","name": "张家界"}, {"id": 323,"spell": "zhangjiakou","name": "张家口"}, {"id": 324,"spell": "zhangye","name": "张掖"}, {"id": 325,"spell": "zhanjiang","name": "湛江"}, {"id": 326,"spell": "zhaoqing","name": "肇庆"}, {"id": 327,"spell": "zhaotong","name": "昭通"}, {"id": 328,"spell": "zhenjiang","name": "镇江"}, {"id": 329,"spell": "zhongwei","name": "中卫"}, {"id": 330,"spell": "zhoukou","name": "周口"}, {"id": 331,"spell": "zhoushan","name": "舟山"}, {"id": 332,"spell": "zhumadian","name": "驻马店"}, {"id": 333,"spell": "zhuzhou","name": "株洲"}, {"id": 334,"spell": "zibo","name": "淄博"}, {"id": 335,"spell": "zigong","name": "自贡"}, {"id": 336,"spell": "ziyang","name": "资阳"}, {"id": 337,"spell": "zunyi","name": "遵义"}, {"id": 929,"spell": "zanhuang","name": "赞皇"}, {"id": 930,"spell": "zengcheng","name": "增城"}, {"id": 931,"spell": "zhangjiagang","name": "张家港"}, {"id": 932,"spell": "zhangping","name": "漳平"}, {"id": 933,"spell": "zhangpu","name": "漳浦"}, {"id": 934,"spell": "zhangqiu","name": "章丘"}, {"id": 935,"spell": "zhangshu","name": "樟树"}, {"id": 936,"spell": "zhanhua","name": "沾化"}, {"id": 937,"spell": "zhaoxian","name": "赵县"}, {"id": 938,"spell": "zhaoyuan","name": "招远"}, {"id": 939,"spell": "zhengding","name": "正定"}, {"id": 940,"spell": "zhenghe","name": "政和"}, {"id": 941,"spell": "zherong","name": "柘荣"}, {"id": 942,"spell": "zhongmou","name": "中牟"}, {"id": 943,"spell": "zhongxian","name": "忠县"}, {"id": 944,"spell": "zhouning","name": "周宁"}, {"id": 945,"spell": "zhouzhi","name": "周至"}, {"id": 946,"spell": "zhuanghe","name": "庄河"}, {"id": 947,"spell": "zhucheng","name": "诸城"}, {"id": 948,"spell": "zhuji","name": "诸暨"}, {"id": 949,"spell": "zijin","name": "紫金"}, {"id": 950,"spell": "zixi","name": "资溪"}, {"id": 951,"spell": "zoucheng","name": "邹城"}, {"id": 952,"spell": "zouping","name": "邹平"}, {"id": 953,"spell": "zunhua","name": "遵化"}]}}
}

2.父子组件间传值 - - - 编辑’City.vue’

<template><div><city-header></city-header><city-search></city-search><city-list :cities='cities' :hot='hotCities'></city-list><city-alphabet :cities='cities'></city-alphabet></div>
</template><script>
import CityHeader from './components/Header'
import CitySearch from './components/Search'
import CityList from './components/List'
import CityAlphabet from './components/Alphabet'
import axios from 'axios'export default {name: 'City',components: {CityHeader,CitySearch,CityList,CityAlphabet},data () {return {cities: {},hotCities: []}},methods: {getCityInfo () {axios.get('/api/city.json').then(this.handleGetCityInfoSucc)},handleGetCityInfoSucc (res) {// console.log(res)res = res.dataif (res.ret && res.data) {const data = res.datathis.cities = data.citiesthis.hotCities = data.hotCities}}},mounted () {this.getCityInfo()}
}
</script><style>
</style>

3.List接收数据 - - - 编辑’List.vue’

<template><!-- ref用来获取DOM --><div class="list" ref="wrapper"><div><div class="area"><div class="title border-topbottom">当前城市</div><div class="button-list"><div class="button-wrapper"><div class="button">武汉</div></div></div></div><div class="area"><div class="title border-topbottom">热门城市</div><div class="button-list"><div class="button-wrapper" v-for="item of hot" :key="item.id"><div class="button">{{item.name}}</div></div></div></div><!-- cities是对象,对象不能直接传值 --><div class="area" v-for="(item, key) of cities" :key="key"><div class="title border-topbottom">{{key}}</div><!-- 二次循环 --><div class="item-list" v-for="innerItem of item" :key="innerItem.id"><div class="item border-bottom">{{innerItem.name}}</div></div></div></div></div>
</template><script>
import BetterScroll from 'better-scroll'
export default {name: 'CityList',props: {hot: Array,cities: Object},mounted () {this.scroll = new BetterScroll(this.$refs.wrapper)},// 页面加载时,内容为空,不会超出页面高度,导致滑动失效// 生命周期函数,当页面加载完成之后,再加载scroll,实现滑动效果updated() {this.scroll.refresh()}
}
</script><style lang="stylus" scoped>
@import '~styles/varibles';// 定义一个类.border-topbottom// 其中的元素&:before// 修改其中的样式border-color #ccc&:afterborder-color #ccc.border-bottom&:beforeborder-color #ccc.list// 超出部分隐藏会导致页面无法滑动overflow hiddenposition absolutetop 1.58rembottom 0left 0right 0// background #000.titleline-height .54remcolor #666font-size .26rempadding-left .2rembackground #eee.button-listoverflow hiddenpadding .1rem .6rem .1rem .1rem.button-wrapperfloat leftwidth 33.33%.buttonmargin .1rempadding .1rem 0text-align centerborder .02rem solid #cccborder-radius .06rem.item-list.itempadding-left .2remline-height .7rem
</style>

4.Alphabet接收数据 - - - 编辑’Alphabet.vue’

<template><ul class="list"><li class="item" v-for='(item, key) of cities' :key='key'>{{key}}</li></ul>
</template><script>
export default {name: 'CityAlphabet',props: {cities: Object}
}
</script><style lang="stylus" scoped>
@import '~styles/varibles'.listdisplay flex// 该布局内部的子控件排列方式是纵向排列,即从上往下flex-direction column// 内容对齐属性应用在弹性容器上,把弹性项沿着弹性容器的主轴线对齐justify-content center// A不参与排列,BCD依次从顶上排列下来position absolutetop 1.58rembottom 0right 0width .4rem.itemline-height .4remtext-align centercolor $bgColor
</style>

七、字母表(Alphabet)功能

1.兄弟组件数值传递 - - - 点击Alphabet的字母,List跳转至对应的首字母城市

a.编辑’Alphabet.vue’文件(路径: src/pages/city/Alphabet.vue) - - - 将点击的字母向外传出

<template><ul class="list"><li class="item" v-for='(item, key) of cities' :key='key' @click="handleLetterClick">{{key}}</li></ul>
</template><script>
export default {name: 'CityAlphabet',props: {cities: Object},methods: {handleLetterClick (e) {// console.log(e.target.innerText)// 向外触发事件this.$emit('change', e.target.innerText)}}
}
</script><style lang="stylus" scoped>
@import '~styles/varibles'.listdisplay flex// 该布局内部的子控件排列方式是纵向排列,即从上往下flex-direction column// 内容对齐属性应用在弹性容器上,把弹性项沿着弹性容器的主轴线对齐justify-content center// A不参与排列,BCD依次从顶上排列下来position absolutetop 1.58rembottom 0right 0width .4rem.itemline-height .4remtext-align centercolor $bgColor
</style>

b.编辑’City.vue’文件(路径: src/pages/City.vue) - - - 监听子组件的传值,并向另一个子组件传值

<template><div><city-header></city-header><city-search></city-search><!-- 父组件向子组件传值 --><city-list :cities='cities' :hot='hotCities' :letter='letter'></city-list><!-- 监听子组件的点击事件 --><city-alphabet :cities='cities'  @change="handleLetterChange"></city-alphabet></div>
</template><script>
import CityHeader from './components/Header'
import CitySearch from './components/Search'
import CityList from './components/List'
import CityAlphabet from './components/Alphabet'
import axios from 'axios'export default {name: 'City',components: {CityHeader,CitySearch,CityList,CityAlphabet},data () {return {cities: {},hotCities: [],// 定义一个新的数据letter,为子组件传值做准备letter: ''}},methods: {getCityInfo () {axios.get('/api/city.json').then(this.handleGetCityInfoSucc)},handleGetCityInfoSucc (res) {// console.log(res)res = res.dataif (res.ret && res.data) {const data = res.datathis.cities = data.citiesthis.hotCities = data.hotCities}},// 接收到子组件传来的数据,进行定义handleLetterChange (letter) {// console.log(letter)this.letter = letter}},mounted () {this.getCityInfo()}
}
</script><style>
</style>

c.编辑’List.vue’文件(路径: src/pages/city/List.vue) - - - 接收父组件传值

<template><!-- ref用来获取DOM --><div class="list" ref="wrapper"><div><div class="area"><div class="title border-topbottom">当前城市</div><div class="button-list"><div class="button-wrapper"><div class="button">武汉</div></div></div></div><div class="area"><div class="title border-topbottom">热门城市</div><div class="button-list"><div class="button-wrapper" v-for="item of hot" :key="item.id"><div class="button">{{item.name}}</div></div></div></div><!-- cities是对象,对象不能直接传值 --><div class="area" v-for="(item, key) of cities" :key="key" :ref="key"><div class="title border-topbottom">{{key}}</div><!-- 二次循环 --><div class="item-list" v-for="innerItem of item" :key="innerItem.id"><div class="item border-bottom">{{innerItem.name}}</div></div></div></div></div>
</template><script>
import BetterScroll from 'better-scroll'
export default {name: 'CityList',props: {hot: Array,cities: Object,// 接收父组件的传值letter: String},mounted () {this.scroll = new BetterScroll(this.$refs.wrapper)},  // 侦听器  监听letter数据改变watch: {letter () {// console.log(this.letter)if (this.letter) {// 通过ref的letter字母,所对应的区域// this.letter返回的是一个数组,所以需要加上[0]const element = this.$refs[this.letter][0]// console.log(element)// 滚动到相应首字母的城市区域// element需要是一个Dom的元素或者元素选择器this.scroll.scrollToElement(element)}}},// 页面加载时,内容为空,不会超出页面高度,导致滑动失效// 生命周期函数,当页面加载完成之后,再加载scroll,实现滑动效果updated() {this.scroll.refresh()}
}
</script><style lang="stylus" scoped>
@import '~styles/varibles';// 定义一个类.border-topbottom// 其中的元素&:before// 修改其中的样式border-color #ccc&:afterborder-color #ccc.border-bottom&:beforeborder-color #ccc.list// 超出部分隐藏会导致页面无法滑动overflow hiddenposition absolutetop 1.58rembottom 0left 0right 0// background #000.titleline-height .54remcolor #666font-size .26rempadding-left .2rembackground #eee.button-listoverflow hiddenpadding .1rem .6rem .1rem .1rem.button-wrapperfloat leftwidth 33.33%.buttonmargin .1rempadding .1rem 0text-align centerborder .02rem solid #cccborder-radius .06rem.item-list.itempadding-left .2remline-height .7rem
</style>

2.兄弟组件数值传递 - - - 滚动Alphabet字母表,List城市列表相应滚动

a.编辑’Alphabet.vue’文件(路径: src/pages/city/Alphabet.vue)

思路:直接计算手指在哪个字母上面比较麻烦, 可以先计算A距离顶部的距离, 再计算手指距离顶部的距离, 差值除以字母的高度, 就可以定位到字母的位置了

<template><ul class="list"><liclass="item"v-for='item of letters':key='item':ref='item'@click="handleLetterClick"@touchstart="handleTouchStart"@touchmove="handleTouchMove"@touchend="handleTouchEnd">{{item}}</li></ul>
</template><script>
export default {name: 'CityAlphabet',props: {cities: Object},// 需要一个数组,存储所需要的字母来进行计算computed: {letters () {const letters = []for (let i in this.cities) {letters.push(i)}return (letters)// 返回的为['A', 'B', 'C,...]}},data () {return {touchStatus: false,// 设置startY初始值为0startY: 0}},methods: {handleLetterClick (e) {// console.log(e.target.innerText)// 向外触发事件this.$emit('change', e.target.innerText)},handleTouchStart () {this.touchStatus = true},handleTouchMove (e) {// 思路: 直接计算手指在哪个字母上面比较麻烦, 可以先计算A距离顶部的距离, 再计算手指距离顶部的距离, 差值除以字母的高度, 就可以定位到字母的位置了if (this.touchStatus) {// 性能问题: 因为startY是固定的,所以需要不断的获取它的值(可以用生命周期函数)// 获取A元素距离顶部的高度const startY = this.$refs['A'][0].offsetTop// const touchY = e.touches[0].clientY// console.log(startY)// 获取手指距离顶部的高度const touchY = e.touches[0].clientY - 79// console.log(touchY)// 计算手指距离A顶部的距离, 再向下取整const index = Math.floor((touchY - startY) / 20)// const index = Math.floor((touchY - this.startY) / 20)// console.log(index)if (index >= 0 && index < this.letters.length) {this.$emit('change', this.letters[index])}}},handleTouchEnd () {this.touchStatus = false}}
}
</script><style lang="stylus" scoped>
@import '~styles/varibles'.listdisplay flex// 该布局内部的子控件排列方式是纵向排列,即从上往下flex-direction column// 内容对齐属性应用在弹性容器上,把弹性项沿着弹性容器的主轴线对齐justify-content center// A不参与排列,BCD依次从顶上排列下来position absolutetop 1.58rembottom 0right 0width .4rem.itemline-height .4remtext-align centercolor $bgColor
</style>

b.优化性能 - - - 函数节流、生命周期钩子

<template><ul class="list"><liclass="item"v-for='item of letters':key='item':ref='item'@click="handleLetterClick"@touchstart="handleTouchStart"@touchmove="handleTouchMove"@touchend="handleTouchEnd">{{item}}</li></ul>
</template><script>
export default {name: 'CityAlphabet',props: {cities: Object},// 需要一个数组,存储所需要的字母来进行计算computed: {letters () {const letters = []for (let i in this.cities) {letters.push(i)}return (letters)// 返回的为['A', 'B', 'C,...]}},data () {return {touchStatus: false,// 设置startY初始值为0startY: 0,// 设置timer为空timer: null}},// 生命周期钩子:当页面初次加载时,当前页面无内容,向ajax请求数据后,内容才会被渲染出来,当字母表内容发生变化时,updated这个生命周期钩子才会被执行,此时A字母距离顶部的距离才不会出现问题updated () {this.startY = this.$refs['A'][0].offsetTop},methods: {handleLetterClick (e) {// console.log(e.target.innerText)// 向外触发事件this.$emit('change', e.target.innerText)},handleTouchStart () {this.touchStatus = true},handleTouchMove (e) {// 思路: 直接计算手指在哪个字母上面比较麻烦, 可以先计算A距离顶部的距离, 再计算手指距离顶部的距离, 差值除以字母的高度, 就可以定位到字母的位置了if (this.touchStatus) {// 通过函数节流的方式,大大减少handleTouchMove的操作频率,提高网页性能;// 执行滚动操作时, 会延迟的5毫秒再执行;如果还在滚动, 则清除上一步操作, 执行新的操作if (this.timer) {clearTimeout(this.timer)}this.timer = setTimeout(() => {// 性能问题: 因为startY是固定的,所以需要不断的获取它的值(可以用生命周期函数)// 获取A元素距离顶部的高度// const startY = this.$refs['A'][0].offsetTop// const touchY = e.touches[0].clientY// console.log(startY)// 获取手指距离顶部的高度const touchY = e.touches[0].clientY - 79// console.log(touchY)// 计算手指距离A顶部的距离, 再向下取整// const index = Math.floor((touchY - startY) / 20)const index = Math.floor((touchY - this.startY) / 20)// console.log(index)if (index >= 0 && index < this.letters.length) {this.$emit('change', this.letters[index])}}, 5)}},handleTouchEnd () {this.touchStatus = false}}
}
</script><style lang="stylus" scoped>
@import '~styles/varibles'.listdisplay flex// 该布局内部的子控件排列方式是纵向排列,即从上往下flex-direction column// 内容对齐属性应用在弹性容器上,把弹性项沿着弹性容器的主轴线对齐justify-content center// A不参与排列,BCD依次从顶上排列下来position absolutetop 1.58rembottom 0right 0width .4rem.itemline-height .4remtext-align centercolor $bgColor
</style>

八、搜索(Search)功能

1.实现搜索显示城市

a.编辑’City.vue’文件(路径: src/pages/City.vue) - - - 父组件传值

<template><div><city-header></city-header><city-search :cities='cities'></city-search><!-- 父组件向子组件传值 --><city-list :cities='cities' :hot='hotCities' :letter='letter'></city-list><!-- 监听子组件的点击事件 --><city-alphabet :cities='cities'  @change="handleLetterChange"></city-alphabet></div>
</template>

b.编辑’Search.vue’文件(路径: src/pages/city/components/Search.vue)

<template><div><div class="search"><input v-model="keyword" class="search-input" type="text" placeholder="请输入城市名或者拼音"></div><!-- 将搜索出来的城市项目做循环 --><div class='search-content'><ul><li class='search-item border-bottom' v-for="item of list" :key="item.id">{{item.name}}</li></ul></div></div>
</template><script>
export default {name: 'CitySearch',props: {cities: Object},data () {return {keyword: '',timer: '',list: []}},watch: {// 监听keyword的变化keyword () {if (this.timer) {clearTimeout(this.timer)}// 如果输入框清空,需要重新渲染数据if (!this.keyword) {this.list = []return}this.timer = setTimeout(() => {// 创建result为一个空数组const result = []// 通过i来循环citiesfor (let i in this.cities) {// 把cities里面的每一个值进行一次遍历this.cities[i].forEach((value) => {// value里面包含了name、spell这两项数据if (value.spell.indexOf(this.keyword) > -1 ||value.name.indexOf(this.keyword) > -1) {// 如能搜索到这些关键词,就把这一项添加到result之中result.push(value)}})}// 循环过后,把result设置到list里面,list里面就存储了搜索到的这些城市项目this.list = result}, 100)}},
}
</script><style lang="stylus" scoped>
@import '~styles/varibles';.searchheight .72rembackground $bgColorpadding 0 .1rem.search-inputwidth 100%height .62remline-height .62remborder-radius .1remtext-align centercolor #666// 解决输入的文本紧贴边缘的问题box-sizing border-boxpadding 0 .1rem.search-contentz-index 1position absoluteoverflow hiddentop 1.58remleft 0right 0bottom 0background #eee.search-itemline-height .7rempadding-left .2remcolor #666background #fff
</style>

2.完善搜索页面 - - - 滚动、显隐、优化

<template><div><div class="search"><input v-model="keyword" class="search-input" type="text" value="搜索关键字" placeholder="请输入城市名或者拼音"></div><!-- 将搜索出来的城市项目做循环 --><div class='search-content' ref='search' v-show="keyword"><ul><li class='search-item border-bottom' v-for="item of list" :key="item.id">{{item.name}}</li><!-- list长度为零时显示的内容 --><!-- 模板里面尽量不要涉及逻辑运算 --><!-- <li class="search-item border-bottom" v-show="!list.length"> --><li class="search-item border-bottom" v-show="hasNoData">哎呀~没有找到匹配城市</li></ul></div></div>
</template><script>
import BetterScroll from 'better-scroll'
export default {name: 'CitySearch',props: {cities: Object},data () {return {keyword: '',timer: '',list: []}},computed: {hasNoData () {return !this.list.length}},watch: {// 监听keyword的变化keyword () {if (this.timer) {clearTimeout(this.timer)}// 如果输入框清空,list搜索内容就为空if (!this.keyword) {this.list = []return}this.timer = setTimeout(() => {// 创建result为一个空数组const result = []// 通过i来循环citiesfor (let i in this.cities) {// 把cities里面的每一个值进行一次遍历this.cities[i].forEach((value) => {// value里面包含了name、spell这两项数据if (value.spell.indexOf(this.keyword) > -1 ||value.name.indexOf(this.keyword) > -1) {// 如能搜索到这些关键词,就把这一项添加到result之中result.push(value)}})}// 循环过后,把result设置到list里面,list里面就存储了搜索到的这些城市项目this.list = result}, 100)}},// 实现滚动效果mounted () {this.scroll = new BetterScroll(this.$refs.search, {// 才可以被点击// click: true})},// 页面加载时,内容为空,不会超出页面高度,导致滑动失效// 生命周期函数,当页面加载完成之后,再加载scroll,实现滑动效果updated() {this.scroll.refresh()}
}
</script><style lang="stylus" scoped>
@import '~styles/varibles';.searchheight .72rembackground $bgColorpadding 0 .1rem.search-inputwidth 100%height .62remline-height .62remborder-radius .1remtext-align centercolor #666// 解决输入的文本紧贴边缘的问题box-sizing border-boxpadding 0 .1rem.search-contentz-index 1position absoluteoverflow hiddentop 1.58remleft 0right 0bottom 0background #eee.search-itemline-height .7rempadding-left .2remcolor #666background #fff
</style>

九、Vuex实现数据共享

1. 默认城市 - - - 首页和选择页面实现数据共享

a.原理


我们把公用的数据放到公用的空间去进行存储,某一个组件改动了公用数据,其他组件就能感知到
State: 驱动应用的数据源,我们所有的公用数据
Actions: 响应在 view 上的用户输入导致的状态变化; 组件去调用actions
Mutations: 一个个同步地对State的修改

b.安装vuex

npm install vuex --save

c.编辑’index.js’文件(路径: src/store/index.js)

import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({state: {city: '武汉'},mutations: {},actions: {},modules: {}
})

d.编辑’main.js’文件(路径: src/main.js)

在main.js里面创建根实例的时候,把store传递进去了,紧接着vuex创建的这个store会被派发到每一个子组件,其他组件可以通过’this.$store’获取

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// css样式
import 'styles/reset.css'
// 解决1px倍率问题
import 'styles/border.css'
// 引用iconfont
import 'styles/iconfont.css'
// 引用轮播图插件
import VueAwesomeSwiper from 'vue-awesome-swiper'
// 引用轮播图插件的css样式
import 'swiper/dist/css/swiper.css'Vue.config.productionTip = false
// 用轮播图插件
Vue.use(VueAwesomeSwiper)new Vue({router,store,render: h => h(App)
}).$mount('#app')

e.编辑’Home.vue’文件(路径: src/pages/home/Home.js)

<template><div><!-- <home-header :city='city'></home-header> --><home-header></home-header><home-swiper :List='swiperList'></home-swiper><home-icons :List='iconList'></home-icons><home-recommend :List='recommendList'></home-recommend><home-weekend :List='weekendList'></home-weekend></div>
</template><script>
// 引用Header组件
import HomeHeader from './components/Header'
import HomeSwiper from './components/Swiper'
import HomeIcons from './components/Icons'
import HomeRecommend from './components/Recommend'
import HomeWeekend from './components/Weekend'
import axios from 'axios'export default {name: 'Home',components: {HomeHeader,HomeSwiper,HomeIcons,HomeRecommend,HomeWeekend},data () {return {// city: '',swiperList: [],iconList: [],recommendList: [],weekendList: []}},methods: {// 创建一个函数getHomeInfo () {// 通过axios进行数据请求axios.get('/api/index.json').then(this.getHomeInfoSucc)},getHomeInfoSucc (res) {// console.log(res)res = res.data// 如果后端返回了数值,并且有data这个数据项if (res.ret && res.data) {// 定义一个'data'='res.data'const data = res.data// ajix里面的'data.city'传给了'city'// this.city = data.city// swiperList里面的数据进行传输this.swiperList = data.swiperList// iconList里面的数据进行传输this.iconList = data.iconList// recommendList里面的数据进行传输this.recommendList = data.recommendList// weekendList里面的数据进行传输this.weekendList = data.weekendList}}},// 创建一个生命周期函数,当页面挂载好了之后,执行这个函数mounted () {this.getHomeInfo()}
}
</script><style>
</style>

f.编辑’index.vue’文件(路径: public/mock/index.json)

去掉’北京’

    "data": {"city":"北京",

g.编辑’Header.vue’文件(路径: src/pages/home/components/Header.vue)

<template><div class="header"><div class="header-left"><span class="iconfont back-icon">&#xe743;</span></div><div class="header-input"><span class='iconfont'>&#xe632;</span>输入城市、景点、游玩主题...</div> <!-- 添加跳转至city的路径  但是会导致链接内容变绿色 --><router-link to="/city"><div class="header-right"><!-- 城市 --><!-- {{this.city}} --><!-- 在main.js里面创建根实例的时候,把store传递进去了,紧接着vuex创建的这个store会被派发到每一个子组件,其他组件可以通过'this.$store'获取 -->{{this.$store.state.city}}<span class="iconfont arrow-icon">&#xe65c;</span></div></router-link></div>
</template>

h.编辑’List.vue’文件(路径: src/pages/city/components/List.vue)

<template><!-- ref用来获取DOM --><div class="list" ref="wrapper"><div><div class="area"><div class="title border-topbottom">当前城市</div><div class="button-list"><div class="button-wrapper"><div class="button">{{this.$store.state.city}}</div></div></div></div><div class="area"><div class="title border-topbottom">热门城市</div><div class="button-list"><div class="button-wrapper" v-for="item of hot" :key="item.id"><div class="button">{{item.name}}</div></div></div></div><!-- cities是对象,对象不能直接传值 --><div class="area" v-for="(item, key) of cities" :key="key" :ref="key"><div class="title border-topbottom">{{key}}</div><!-- 二次循环 --><div class="item-list" v-for="innerItem of item" :key="innerItem.id"><div class="item border-bottom">{{innerItem.name}}</div></div></div></div></div>
</template>

2. 选择城市后,城市列表的当前城市发生改变

a.编辑’List.vue’文件(路径: src/pages/city/components/List.vue)

<template><!-- ref用来获取DOM --><div class="list" ref="wrapper"><div><div class="area"><div class="title border-topbottom">当前城市</div><div class="button-list"><div class="button-wrapper"><div class="button">{{this.$store.state.city}}</div></div></div></div><div class="area"><div class="title border-topbottom">热门城市</div><div class="button-list"><div class="button-wrapper" v-for="item of hot" :key="item.id" @click="handleCityClick(item.name)"><div class="button">{{item.name}}</div></div></div></div><!-- cities是对象,对象不能直接传值 --><div class="area" v-for="(item, key) of cities" :key="key" :ref="key"><div class="title border-topbottom">{{key}}</div><!-- 二次循环 --><div class="item-list"><div class="item border-bottom"  v-for="innerItem of item" :key="innerItem.id">{{innerItem.name}}</div></div></div></div></div>
</template><script>
import BetterScroll from 'better-scroll'
export default {name: 'CityList',props: {hot: Array,cities: Object,// 接收父组件的传值letter: String},methods: {handleCityClick (city) {// alert(city)// 派发一个changeCity的方法,把city传过去this.$store.dispatch('changeCity', city)// this.$store.commit('changeCity', city)this.changeCity(city)// 修改城市之后,跳转到首页// this.$router.push('/')}},mounted () {this.scroll = new BetterScroll(this.$refs.wrapper), {click: true,mouseWheel: true,tap: true,disableMouse: false,disableTouch: false}}, // 侦听器  监听letter数据改变watch: {letter () {// console.log(this.letter)if (this.letter) {// 通过ref的letter字母,所对应的区域// this.letter返回的是一个数组,所以需要加上[0]const element = this.$refs[this.letter][0]// console.log(element)// 滚动到相应首字母的城市区域// element需要是一个Dom的元素或者元素选择器this.scroll.scrollToElement(element)}},},// 页面加载时,内容为空,不会超出页面高度,导致滑动失效// 生命周期函数,当页面加载完成之后,再加载scroll,实现滑动效果updated() {this.scroll.refresh()}
}
</script><style lang="stylus" scoped>
@import '~styles/varibles';// 定义一个类.border-topbottom// 其中的元素&:before// 修改其中的样式border-color #ccc&:afterborder-color #ccc.border-bottom&:beforeborder-color #ccc.list// 超出部分隐藏会导致页面无法滑动overflow hiddenposition absolutetop 1.58rembottom 0left 0right 0// background #000.titleline-height .54remcolor #666font-size .26rempadding-left .2rembackground #eee.button-listoverflow hiddenpadding .1rem .6rem .1rem .1rem.button-wrapperfloat leftwidth 33.33%.buttonmargin .1rempadding .1rem 0text-align centerborder .02rem solid #cccborder-radius .06rem.item-list.itempadding-left .2remline-height .7rem
</style>

b.编辑’index.js’文件(路径: src/store/index.js)

import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({state: {city: '武汉'},// 不涉及异步操作和批量操作,操作简单,所以可以跳过Actionsactions: {changeCity (ctx, city) {// console.log(city)// 通过上下文ctx来拿到commit这个方法ctx.commit('changeCity', city)}},mutations: {changeCity (state, city) {// 使公用数据city等于我们传入的数据state.city = city// 实现本地存储// localStorage.city = city}},modules: {}
})

c.编辑’List.vue’文件(路径: src/pages/city/components/List.vue) - - - 实现了点击城市返回首页,且首页的城市被切换

<template><!-- ref用来获取DOM --><div class="list" ref="wrapper"><div><div class="area"><div class="title border-topbottom">当前城市</div><div class="button-list"><div class="button-wrapper"><div class="button">{{this.$store.state.city}}</div></div></div></div><div class="area"><div class="title border-topbottom">热门城市</div><div class="button-list"><div class="button-wrapper" v-for="item of hot" :key="item.id" @click="handleCityClick(item.name)"><div class="button">{{item.name}}</div></div></div></div><!-- cities是对象,对象不能直接传值 --><div class="area" v-for="(item, key) of cities" :key="key" :ref="key"><div class="title border-topbottom">{{key}}</div><!-- 二次循环 --><div class="item-list"><div class="item border-bottom"  v-for="innerItem of item" :key="innerItem.id" @click="handleCityClick(innerItem.name)">{{innerItem.name}}</div></div></div></div></div>
</template><script>
import BetterScroll from 'better-scroll'
export default {name: 'CityList',props: {hot: Array,cities: Object,// 接收父组件的传值letter: String},methods: {handleCityClick (city) {// alert(city)// actions可以暂时不用被调用,直接调用mutations来改变数据(详情查看vuex)// this.$store.dispatch('changeCity', city)this.$store.commit('changeCity', city)this.$router.push('/')}},mounted () {this.scroll = new BetterScroll(this.$refs.wrapper), {click: true,mouseWheel: true,tap: true,disableMouse: false,disableTouch: false}}, // 侦听器  监听letter数据改变watch: {letter () {// console.log(this.letter)if (this.letter) {// 通过ref的letter字母,所对应的区域// this.letter返回的是一个数组,所以需要加上[0]const element = this.$refs[this.letter][0]// console.log(element)// 滚动到相应首字母的城市区域// element需要是一个Dom的元素或者元素选择器this.scroll.scrollToElement(element)}},},// 页面加载时,内容为空,不会超出页面高度,导致滑动失效// 生命周期函数,当页面加载完成之后,再加载scroll,实现滑动效果updated() {this.scroll.refresh()}
}
</script><style lang="stylus" scoped>
@import '~styles/varibles';// 定义一个类.border-topbottom// 其中的元素&:before// 修改其中的样式border-color #ccc&:afterborder-color #ccc.border-bottom&:beforeborder-color #ccc.list// 超出部分隐藏会导致页面无法滑动overflow hiddenposition absolutetop 1.58rembottom 0left 0right 0// background #000.titleline-height .54remcolor #666font-size .26rempadding-left .2rembackground #eee.button-listoverflow hiddenpadding .1rem .6rem .1rem .1rem.button-wrapperfloat leftwidth 33.33%.buttonmargin .1rempadding .1rem 0text-align centerborder .02rem solid #cccborder-radius .06rem.item-list.itempadding-left .2remline-height .7rem
</style>

d.编辑’Search.vue’文件(路径: src/pages/city/components/Search.vue) - - - 实现点击搜索的城市后,返回首页,且首页的城市被切换

<template><div><div class="search"><input v-model="keyword" class="search-input" type="text" value="搜索关键字" placeholder="请输入城市名或者拼音"></div><!-- 将搜索出来的城市项目做循环 --><div class='search-content' ref='search' v-show="keyword"><ul><li class='search-item border-bottom' v-for="item of list" :key="item.id" @click="handleCityClick(item.name)">{{item.name}}</li><!-- list长度为零时显示的内容 --><!-- 模板里面尽量不要涉及逻辑运算 --><!-- <li class="search-item border-bottom" v-show="!list.length"> --><li class="search-item border-bottom" v-show="hasNoData">哎呀~没有找到匹配城市</li></ul></div></div>
</template><script>
import BetterScroll from 'better-scroll'
export default {name: 'CitySearch',props: {cities: Object},data () {return {keyword: '',timer: '',list: []}},computed: {hasNoData () {return !this.list.length}},methods: {handleCityClick (city) {// alert(city)// actions可以暂时不用被调用,直接调用mutations来改变数据(详情查看vuex)// this.$store.dispatch('changeCity', city)this.$store.commit('changeCity', city)this.$router.push('/')}},watch: {// 监听keyword的变化keyword () {if (this.timer) {clearTimeout(this.timer)}// 如果输入框清空,list搜索内容就为空if (!this.keyword) {this.list = []return}this.timer = setTimeout(() => {// 创建result为一个空数组const result = []// 通过i来循环citiesfor (let i in this.cities) {// 把cities里面的每一个值进行一次遍历this.cities[i].forEach((value) => {// value里面包含了name、spell这两项数据if (value.spell.indexOf(this.keyword) > -1 ||value.name.indexOf(this.keyword) > -1) {// 如能搜索到这些关键词,就把这一项添加到result之中result.push(value)}})}// 循环过后,把result设置到list里面,list里面就存储了搜索到的这些城市项目this.list = result}, 100)}},// 实现滚动效果mounted () {this.scroll = new BetterScroll(this.$refs.search, {// 才可以被点击// click: true})},// 页面加载时,内容为空,不会超出页面高度,导致滑动失效// 生命周期函数,当页面加载完成之后,再加载scroll,实现滑动效果updated() {this.scroll.refresh()}
}
</script><style lang="stylus" scoped>
@import '~styles/varibles';.searchheight .72rembackground $bgColorpadding 0 .1rem.search-inputwidth 100%height .62remline-height .62remborder-radius .1remtext-align centercolor #666// 解决输入的文本紧贴边缘的问题box-sizing border-boxpadding 0 .1rem.search-contentz-index 1position absoluteoverflow hiddentop 1.58remleft 0right 0bottom 0background #eee.search-itemline-height .7rempadding-left .2remcolor #666background #fff
</style>

3. Vuex的高级使用及localStorage

a.编辑’index.js’文件(路径: src/store/index.js) - - - 刷新页面后,选择的城市为之前已选择的城市

<template><!-- ref用来获取DOM --><div class="list" ref="wrapper"><div><div class="area"><div class="title border-topbottom">当前城市</div><div class="button-list"><div class="button-wrapper"><div class="button">{{this.$store.state.city}}</div></div></div></div><div class="area"><div class="title border-topbottom">热门城市</div><div class="button-list"><div class="button-wrapper" v-for="item of hot" :key="item.id" @click="handleCityClick(item.name)"><div class="button">{{item.name}}</div></div></div></div><!-- cities是对象,对象不能直接传值 --><div class="area" v-for="(item, key) of cities" :key="key" :ref="key"><div class="title border-topbottom">{{key}}</div><!-- 二次循环 --><div class="item-list"><div class="item border-bottom"  v-for="innerItem of item" :key="innerItem.id">{{innerItem.name}}</div></div></div></div></div>
</template><script>
import BetterScroll from 'better-scroll'
export default {name: 'CityList',props: {hot: Array,cities: Object,// 接收父组件的传值letter: String},methods: {handleCityClick (city) {// alert(city)// 派发一个changeCity的方法,把city传过去this.$store.dispatch('changeCity', city)// this.$store.commit('changeCity', city)this.changeCity(city)// 修改城市之后,跳转到首页// this.$router.push('/')}},mounted () {this.scroll = new BetterScroll(this.$refs.wrapper), {click: true,mouseWheel: true,tap: true,disableMouse: false,disableTouch: false}}, // 侦听器  监听letter数据改变watch: {letter () {// console.log(this.letter)if (this.letter) {// 通过ref的letter字母,所对应的区域// this.letter返回的是一个数组,所以需要加上[0]const element = this.$refs[this.letter][0]// console.log(element)// 滚动到相应首字母的城市区域// element需要是一个Dom的元素或者元素选择器this.scroll.scrollToElement(element)}},},// 页面加载时,内容为空,不会超出页面高度,导致滑动失效// 生命周期函数,当页面加载完成之后,再加载scroll,实现滑动效果updated() {this.scroll.refresh()}
}
</script><style lang="stylus" scoped>
@import '~styles/varibles';// 定义一个类.border-topbottom// 其中的元素&:before// 修改其中的样式border-color #ccc&:afterborder-color #ccc.border-bottom&:beforeborder-color #ccc.list// 超出部分隐藏会导致页面无法滑动overflow hiddenposition absolutetop 1.58rembottom 0left 0right 0// background #000.titleline-height .54remcolor #666font-size .26rempadding-left .2rembackground #eee.button-listoverflow hiddenpadding .1rem .6rem .1rem .1rem.button-wrapperfloat leftwidth 33.33%.buttonmargin .1rempadding .1rem 0text-align centerborder .02rem solid #cccborder-radius .06rem.item-list.itempadding-left .2remline-height .7rem
</style>

b.新建’state.js’文件(路径: src/store/state.js)

let defaultCity = '武汉'
try {if (localStorage.city) {defaultCity = localStorage.city}
} catch (e) {}export default {city: defaultCity
}

c.新建’mutations.js’文件(路径: src/store/mutations.js)

export default {changeCity (state, city) {// 使公用数据city等于我们传入的数据state.city = city// 实现本地存储try {localStorage.city = city} catch (e) {}}
}

4. 完善首页细节

a.编辑’Header.vue’文件(路径: src/pages/home/components/Header.vue) - - - 城市字多了的时候,会换行

    .header-rightfloat right// 宽度不能写死,确定最小宽度,可以使用多字城市min-width 1.04rempadding 0 .1rem

5. Vuex的高级使用

a.编辑’Header.vue’文件(路径: src/pages/home/components/Header.vue) - - - Vuex的mapState用法

<!-- {{this.$store.state.city}} -->{{this.city}}import { mapState } from 'vuex'
export default {name: 'HomeHeader',// props: {//   city: String// }// 把vuex里面的数据映射到computed计算属性里, 把city公用数组映射到city的计算属性中// ...mapputed是展开运算符computed: {...mapState(['city'])// ...mapGetters(['doubleCity'])}
}

b.编辑’List.vue’文件(路径: src/pages/city/components/List.vue) - - - Vuex的mapMutations用法

<!-- {{this.$store.state.city}} -->{{this.currentCity}}import { mapMutations, mapState } from 'vuex'computed: {...mapState({// 把vuex的公用数据city映射到computed这个计算属性里,映射过来的名字叫currentCitycurrentCity: 'city'})},methods: {handleCityClick (city) {this.changeCity(city)this.$router.push('/')},// 有个mutations叫changeCity,我们把mutations映射到changeCity这个组件里,方便changeCity更简便的调用...mapMutations(['changeCity'])},

c.编辑’Search.vue’文件(路径: src/pages/city/components/Search.vue)

import { mapMutations } from 'vuex'methods: {handleCityClick (city) {// alert(city)// actions可以暂时不用被调用,直接调用mutations来改变数据(详情查看vuex)// this.$store.dispatch('changeCity', city)this.$store.commit('changeCity', city)this.$router.push('/')},// 有个mutations叫changeCity,我们把mutations映射到changeCity这个组件里,方便changeCity更简便的调用...mapMutations(['changeCity'])},

6. Vuex的核心概念 - - - Getters的用法

State是存放公用数据、Actions是异步方法、Mutations是同步对数据进行改变、

a.编辑’index.js’文件(路径: src/store/index.js)

export default new Vuex.Store({state: state,mutations: mutations,getters: {// 定义一个doubleCity的对象,他会接受一个参数statedoubleCity (state) {return state.city + ' ' + state.city}}
})

b.编辑’Header.vue’文件(路径: src/pages/home/components/Header.vue)

        <!-- {{this.city}} -->{{this.doubleCity}}<script>
import { mapState, mapGetters } from 'vuex'
export default {name: 'HomeHeader',// props: {//   city: String// }// 把vuex里面的数据映射到computed计算属性里, 把city公用数组映射到city的计算属性中// ...mapputed是展开运算符computed: {...mapState(['city']),...mapGetters(['doubleCity'])}
}

c.作用


类似计算属性的作用,通过state里面的数据计算出新的数据,避免数据的冗余


7. Vuex的核心概念 - - - Module的用法

引用场景: 当我们对面多数据的场景,比如有后台数据,我们把数据都存在到mutations内,他将会变得非常[庞大并且难以维护,这时候就可以通过module对复杂的mutaions进行模块拆分


十、keep-alive优化网页性能

1.编辑’App.vue’文件(路径: src/App.vue)

每一次切换路由,都会使ajax的数据被重新请求一次,比如:首页和城市列表页面,城市会被多次请求

<template><div id="app"><!-- 路由加载过一次之后,就把加载过的内容放到内存之中,下一次加载不需要重新渲染这个组件,直接从路由中调用 --><keep-alive exclude="Detail"><!-- 显示当前路由地址所对应的内容 --><router-view/></keep-alive></div>
</template>

2. 编辑’Home.vue’文件(路径: src/pages/home/components/Home.vue)

切换城市后,首页的内容需要根据切换的城市,被重新渲染一次

import { mapState } from 'vuex'computed: {...mapState(['city'])},methods: {// 创建一个函数getHomeInfo () {// 通过axios进行数据请求// axios.get('/api/index.json')// 切换城市后,需要根据选择的城市重新渲染首页数据axios.get('/api/index.json?city=' + this.city).then(this.getHomeInfoSucc)},

3. 编辑’Home.vue’文件(路径: src/pages/home/components/Home.vue)

因为keep-alive本地存储的原因,首页的数据不会被切换

  data () {return {// 新增lastCitylastCity: '',swiperList: [],iconList: [],recommendList: [],weekendList: []}},// 创建一个生命周期函数,当页面挂载好了之后,执行这个函数// 首次进入页面会被执行,切换城市后进入首页  不  会被执行mounted () {this.lastCity = this.citythis.getHomeInfo()// console.log('mounted')},// 首次进入页面会被执行,切换城市后进入首页  也  会被执行activated () {if (this.lastCity !== this.city) {this.lastCity = this.citythis.getHomeInfo()// console.log('activated')}}

(超级详细)Vue项目实战App3- - - 城市选择相关推荐

  1. 【VUE项目实战】59、订单的物流信息查询功能

    接上篇<58.订单修改收货地址的功能> 上一篇我们完成了订单列表的修改收货地址功能,本篇我们来实现订单的物流信息查询功能. 一.要实现的效果 我们要实现点击操作列的"物流进度&q ...

  2. 【VUE项目实战】64、CND优化ElementUI以及首页内容定制

    接上篇<63.指定打包入口及加载外部CDN资源> 上一篇我们为开发模式与发布模式制定不同的打包入口,然后为项目加载外部CDN资源.本篇我们来学习通过CND优化ElementUI的打包,以及 ...

  3. 【VUE项目实战】56、商品添加功能(六)-提交添加的商品

    接上篇<55.商品添加功能(五)-商品内容模块> 上一篇我们完成了商品内容编辑模块的开发,也即是完成了商品所有的信息编辑,本篇我们就来开发提交商品所有信息到后台的功能. 一.要实现的效果 ...

  4. 【VUE项目实战】54、商品添加功能(四)-商品图片上传模块

    接上篇<53.商品添加功能(三)-商品参数及属性模块> 上一篇我们完成了商品参数和商品属性面板的开发,本篇我们来完成商品图片上传模块的开发. 一.要实现的效果 我们在商品图片页签,需要放置 ...

  5. 【VUE项目实战】41、添加商品分类功能(二)

    接上篇<40.添加商品分类功能(一)> 上一篇我们实现了部分添加商品分类的功能,本篇我们来继续处理添加分类时表单相关的内容. 一.优化上一章剩余的小问题 首先我们先处理一下选中之后想要清除 ...

  6. Vue项目实战 —— 后台管理系统( pc端 ) 第三篇

    ​前期回顾    ​  Vue项目实战 -- 后台管理系统( pc端 ) 第二篇_0.活在风浪里的博客-CSDN博客前期回顾 Vue项目实战 -- 后台管理系统( pc端 ) 第一篇 _0.活在风浪里 ...

  7. Vue项目实战 —— 后台管理系统( pc端 ) 第一篇

    前期回顾     我只写注释 -- 让Ai写代码_0.活在风浪里的博客-CSDN博客前期回顾 Vue项目实战 -- 哔哩哔哩移动端开发-- 第二篇_0.活在风浪里的博客-CSDN博客https://b ...

  8. Vue项目实战-vue2(移动端)

    Vue项目实战(移动端)# 相关资料 (一) 创建项目 (二) 禁用Eslint (三) devtool (四) 添加less支持 (五) vue路由配置(背诵) (六) 父子组件通信(背诵) (七) ...

  9. vue 动态添加class_前端开发:Vue项目实战-Music

    大家好,我来了,本期为大家带来的前端开发知识是"前端开发:Vue项目实战-Music",有兴趣做前端的朋友,和我一起来看看吧! 主要内容 项目环境搭建 路由导航实现 ListVie ...

最新文章

  1. JavaScript的数据类型、null 和undefined、原始数据类型和引用数据类型等JavaScript基础知识总结
  2. 阿里云实时数仓Hologres年度发布,解读数仓新趋势
  3. 轻量级动态线程池才是“王道”?
  4. 系统上关闭是意外的_紧急关闭iOS13,有史以来跳版本关闭系统
  5. taskkill 命令:
  6. 孩子哭的时候大人应该怎么办?
  7. Windows 常用的 CMD 命令
  8. request.getContextPath()
  9. 写高性能 Web 应用程序的 10 个技巧 转自微软资料 .
  10. 2020.10.30文献1:《滇中引水工程香炉山隧洞地应力特征及其活动构造响应》
  11. 中国数据中心改造市场趋势报告、技术动态创新及市场预测
  12. flink写hive hdfs一直挂在.inprogress状态
  13. git clone 报错:fatal: unable to access ‘https://github.com/xxxxxxxxx/xxx.git/‘: gnutls_
  14. 虚拟机中的Linux系统如何联网?
  15. 什么软件能测试苹果手机的配件,爱思助手“正品配件检测”功能使用方法
  16. Html5 获取手机短信号码
  17. 春学期C语言程序设计,2019年春季学期《C语言程序设计II》课程总结
  18. xcode中添加新字体【ttf】
  19. 联想小新Air 13安装黑苹果兼macOS Mojave安装教程
  20. matlab模拟反射,matlab模拟光的反射折射

热门文章

  1. 【Redis】Redis基础知识点
  2. aria2c下载磁力链接
  3. 面向对象系列教材 (一)- Java中的类和对象
  4. 今天给在家介绍一篇健身俱乐部信息管理系统设计与实现
  5. 视频PS神器!人物隐身、水印去除,简直像重拍了一遍,包含开源代码
  6. layuiAdmin 常见问题与解决方案
  7. 智能车摄像头动态打角算法
  8. HTML5期末大作业:水果超市网站设计——水果超市(6页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计 网购商城设置网页
  9. 航模lipo锂电池过放抢救/处理方式
  10. yum mysql 安装client_centos6 只安装mysql client(安装包安装和yum安装mysql)