(最详细)VueApp项目实战3 - - 城市选择
一、路由配置1.目的为了实现从首页可以跳转到城市选择页面2.编辑’index.js’文件(路径: fonfig/index.js) - - - 创建路由的路径import Vue from 'vue'import Router from 'vue-router'import Home from '@/pages/home/Home'// 引入city这个组件import City from '@/
·
一、路由配置
1.目的
为了实现从首页可以跳转到城市选择页面
2.编辑’index.js’文件(路径: fonfig/index.js) - - - 创建路由的路径
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/pages/home/Home'
// 引入city这个组件
import City from '@/pages/city/City'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: Home
}, {
// 创建一个路由
// 路径也是根目录下的city
path: '/city',
// 路由的名字叫City
name: 'City',
// 创建一个city的组件
component: City
}
]
})
二、Ajax动态获取城市数据
1. 创建 'city.json’文件(路径: src/static/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": "遵化"
}]
}
}
}
三、组件化开发
该页面可分为’Header’、‘Search’、‘List’、'Alphabet’四个组件组成
1.创建城市列表首页
a.创建’City’文件夹和’City.vue’文件(路径: src/pages/city/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>
<script>
import axios from 'axios'
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
},
data () {
return {
cities: {},
hotCities: [],
letter: ''
}
},
// 定义这个方法
methods: {
getCityInfo () {
axios.get('/api/city.json')
.then(this.handleGetCityInfoSucc)
},
handleGetCityInfoSucc (res) {
// console.log(res)
res = res.data
if (res.ret && res.data) {
const data = res.data
this.cities = data.cities
this.hotCities = data.hotCities
}
},
handleLetterChange (letter) {
// console.log(letter)
this.letter = letter
}
},
// 创建一个生命周期函数来调用ajax的方法
mounted () {
this.getCityInfo()
}
}
</script>
<style lang="stylus" scoped>
</style>
2.Header
a.编辑’Header.vue’文件(路径: src/pages/home/components/Header.vue) - - - 实现点击’城市’可以跳转到城市选择页
<!-- 实现页面跳转 -->
<router-link to='/city'>
<div class="header-right">
<!-- 城市 -->
<!-- {{this.city}} -->
<!-- 通过前端mand.js传值,而不需要后端传值过来了 -->
<!-- {{this.$store.state.city}} -->
{{this.city}}
<!-- 可以通过getter的计算来获得新的数据 -->
<!-- {{this.doubleCity}} -->
<span class="iconfont arrow-icon"></span>
</div>
</router-link>
b.编辑’City.vue’文件(路径: src/pages/city/City.vue) - - - 引用’Header.vue’组件
<template>
<city-header></city-header>
</template>
<script>
import CityHeader from './components/Header'
export default {
name: 'City',
components: {
CityHeader,
}
</script>
<style lang="stylus" scoped>
</style>
c.编辑’Header.vue’文件(路径: src/pages/home/components/Header.vue) - - - 完善内容
<template>
<div class="header">
<!-- 点击返回,设置路径 -->
<router-link to='./'>
<div class="iconfont header-back"></div>
</router-link>
城市选择
</div>
</template>
<script>
export default {
name: 'CityHeader'
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.header
position relative
overflow hidden
height $headerHight
line-height $headerHight
text-align center
color #fff
background $bgColor
font-size .32rem
.header-back
position absolute
top 0
left 0
width .64rem
text-align center
font-size .4rem
color #fff
</style>
3.Search
a.创建’Search.vue’文件(路径: src/pages/city/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.styl'
</style>
b.编辑’City.vue’文件(路径: src/pages/city/City.vue) - - - 引用’Search.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 lang="stylus" scoped>
</style>
c.编辑’Search.vue’文件(路径: src/pages/city/Search.vue) - - - 完善搜索条
<template>
<div>
<div class="search">
<input
v-model="keyword"
class="search-input"
type="text"
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 { mapMutations } from 'vuex'
import BScroll from 'better-scroll'
export default {
name: 'CitySearch',
props: {
cities: Object
},
data () {
return {
keyword: '',
list: [],
timer: ''
}
},
methods: {
handleCityClick (city) {
this.changeCity(city)
this.$router.push('/')
},
...mapMutations(['changeCity'])
},
computed: {
hasNoData () {
return !this.list.length
}
},
watch: {
keyword () {
if (this.timer) {
clearTimeout(this.timer)
}
// 如果输入框清空,需要重新渲染数据
if (!this.keyword) {
this.list = []
return
}
this.timer = setTimeout(() => {
const result = []
for (let i in this.cities) {
this.cities[i].forEach((value) => {
if (value.spell.indexOf(this.keyword) > -1 ||
value.name.indexOf(this.keyword) > -1) {
result.push(value)
}
})
}
this.list = result
}, 100)
}
},
mounted () {
this.scroll = new BScroll(this.$refs.search, {
click: true
})
}
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.search
height .72rem
padding 0 .1rem
background $bgColor
.search-input
box-sizing border-box
width 100%
height .62rem
padding 0 .1rem
line-height .62rem
text-align center
border-radius .06rem
color #666
.search-content
z-index 1
overflow hidden
position absolute
top 1.58rem
left 0
right 0
bottom 0
background #eee
.search-item
line-height .62rem
padding-left .2rem
color #666
background #fff
</style>
4.List
a.创建’List.vue’文件(路径: src/pages/city/List.vue) - - - 创建城市列表
<template>
<div class="list">
List
</div>
</template>
<script>
export default {
name: 'CityList'
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
</style>
b.编辑’City.vue’文件(路径: src/pages/city/City.vue) - - - 引用’LIst.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 CitySearch from './components/List'
export default {
name: 'City',
components: {
CityHeader,
CitySearch,
CityList
}
</script>
<style lang="stylus" scoped>
</style>
c.编辑’List.vue’文件(路径: src/pages/city/List.vue) - - - 完善城市列表
<template>
<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}} -->
{{this.currentCity}}
</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>
<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>
// 引入better-scroll
import BScroll from 'better-scroll'
import { mapState, mapMutations } from 'vuex'
export default {
name: 'CityList',
props: {
hot: Array,
cities: Object,
letter: String
},
computed: {
...mapState({
currentCity: 'city'
})
},
// methods: {
// handleCityClick (city) {
// // alert(city)
// // this.$store.dispatch('changeCity', city)
// // this.$store.commit('changeCity', city)
// this.changeCity(city)
// // 修改城市之后,跳转到首页
// this.$router.push('/')
// },
// ...mapMutations(['changeCity'])
// },
methods: {
handleCityClick (city) {
this.changeCity(city)
this.$router.push('/')
},
...mapMutations(['changeCity'])
},
// 侦听器 监听letter数据改变
watch: {
letter () {
if (this.letter) {
const element = this.$refs[this.letter][0]
// console.log(element)
this.scroll.scrollToElement(element)
}
// console.log(this.letter)
},
cities () {
this.$nextTick(function () {
this.scroll = new BScroll(this.$refs.wrapper, {
click: true,
mouseWheel: true,
tap: true,
disableMouse: false,
disableTouch: false
})
})
}
}
// 创建一个生命周期函数
// mounted () {
// // // 创建一个scroll实例
// // // this.scroll = new Bscroll(this.$refs.wrapper)
// // // console.log(BScroll)
// this.$nextTick(function () {
// this.scroll = new BScroll(this.$refs.wrapper, {
// click: true,
// mouseWheel: true,
// tap: true,
// disableMouse: false,
// disableTouch: false
// })
// })
// // this.scroll = new Bscroll(this.$refs.wrapper, {
// // click: true
// // })
// // this.scroll = new Bscroll(this.$refs.wrapper, {
// // click: true})
// }
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.border-topbottom
&:before
border-color #ccc
&:after
border-color #ccc
.border-bottom
&:before
border-color #ccc
.list
overflow hidden
position absolute
top 1.58rem
left 0
right 0
bottom 0
.title
line-height .54rem
color #666
font-size .26rem
padding-left .2rem
background #eee
.button-list
overflow hidden
padding .1rem .6rem .1rem .1rem
.button-wrapper
float left
width 33.33%
.button
margin .1rem
padding .1rem 0
text-align center
border .02rem solid #ccc
border-radius .06rem
.item-list
.item
line-height .76rem
padding-left .2rem
</style>
5.Alphabet
a.创建’Alphabet.vue’文件(路径: src/pages/city/Alphabet.vue) - - - 创建右侧字母表
<template>
<ul class="list">
<!-- 点击字母时,触发跳转事件 -->
<!-- v-for="(item, key) of cities" -->
<!-- :key="key" -->
<li
class="item"
v-for="item of letters"
:key="item"
:ref="item"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
@click="handleLetterClick"
>
<!-- {{key}} -->
{{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初始值为0
startY: 0,
// 设置timer为空
timer: null
}
},
// 创建一个生命周期钩子
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的操作频率,提高网页性能;
// 执行滚动操作时, 会延迟的16毫秒再执行;如果还在滚动, 则清除上一步操作, 执行新的操作
if (this.timer) {
clearTimeout(this.timer)
}
this.timer = setTimeout(() => {
// 性能问题: 因为startY是固定的,所以需要不断的获取它的值(可以用生命周期函数)
// 获取A元素距离顶部的高度
// const startY = this.$refs['A'][0].offsetTop
// 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.styl'
.list
display flex
flex-direction column
justify-content center
position absolute
top 1.58rem
bottom 0
right 0
width .4rem
// background red
.item
line-height .4rem
text-align center
color $bgColor
</style>
b.编辑’City.vue’文件(路径: src/pages/city/City.vue) - - - 引用’Alphabet.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 CitySearch from './components/List'
import CitySearch from './components/Alphabet'
export default {
name: 'City',
components: {
CityHeader,
CitySearch,
CityList,
Alphabet
}
</script>
<style lang="stylus" scoped>
</style>
6.兄弟组件数值传递 - - - 点击字母表,跳转至相应城市
a.编辑’Alphabet.vue’文件(路径: src/pages/city/Alphabet.vue) - - - 点击左侧字母表
<template>
<ul class="list">
<!-- 点击字母时,触发跳转事件 -->
<!-- v-for="(item, key) of cities" -->
<!-- :key="key" -->
<li
class="item"
v-for="item of letters"
:key="item"
:ref="item"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
@click="handleLetterClick"
>
<!-- {{key}} -->
{{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初始值为0
startY: 0,
// 设置timer为空
timer: null
}
},
// 创建一个生命周期钩子
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的操作频率,提高网页性能;
// 执行滚动操作时, 会延迟的16毫秒再执行;如果还在滚动, 则清除上一步操作, 执行新的操作
if (this.timer) {
clearTimeout(this.timer)
}
this.timer = setTimeout(() => {
// 性能问题: 因为startY是固定的,所以需要不断的获取它的值(可以用生命周期函数)
// 获取A元素距离顶部的高度
// const startY = this.$refs['A'][0].offsetTop
// 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.styl'
.list
display flex
flex-direction column
justify-content center
position absolute
top 1.58rem
bottom 0
right 0
width .4rem
// background red
.item
line-height .4rem
text-align center
color $bgColor
</style>
b.编辑’List.vue’文件(路径: src/pages/city/List.vue) - - - 右侧城市列表跳转到相应首字母城市
<template>
<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}} -->
{{this.currentCity}}
</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>
<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>
// 引入better-scroll
import BScroll from 'better-scroll'
import { mapState, mapMutations } from 'vuex'
export default {
name: 'CityList',
props: {
hot: Array,
cities: Object,
letter: String
},
computed: {
...mapState({
currentCity: 'city'
})
},
// methods: {
// handleCityClick (city) {
// // alert(city)
// // this.$store.dispatch('changeCity', city)
// // this.$store.commit('changeCity', city)
// this.changeCity(city)
// // 修改城市之后,跳转到首页
// this.$router.push('/')
// },
// ...mapMutations(['changeCity'])
// },
methods: {
handleCityClick (city) {
this.changeCity(city)
this.$router.push('/')
},
...mapMutations(['changeCity'])
},
// 侦听器 监听letter数据改变
watch: {
letter () {
if (this.letter) {
const element = this.$refs[this.letter][0]
// console.log(element)
this.scroll.scrollToElement(element)
}
// console.log(this.letter)
},
cities () {
this.$nextTick(function () {
this.scroll = new BScroll(this.$refs.wrapper, {
click: true,
mouseWheel: true,
tap: true,
disableMouse: false,
disableTouch: false
})
})
}
}
// 创建一个生命周期函数
// mounted () {
// // // 创建一个scroll实例
// // // this.scroll = new Bscroll(this.$refs.wrapper)
// // // console.log(BScroll)
// this.$nextTick(function () {
// this.scroll = new BScroll(this.$refs.wrapper, {
// click: true,
// mouseWheel: true,
// tap: true,
// disableMouse: false,
// disableTouch: false
// })
// })
// // this.scroll = new Bscroll(this.$refs.wrapper, {
// // click: true
// // })
// // this.scroll = new Bscroll(this.$refs.wrapper, {
// // click: true})
// }
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.border-topbottom
&:before
border-color #ccc
&:after
border-color #ccc
.border-bottom
&:before
border-color #ccc
.list
overflow hidden
position absolute
top 1.58rem
left 0
right 0
bottom 0
.title
line-height .54rem
color #666
font-size .26rem
padding-left .2rem
background #eee
.button-list
overflow hidden
padding .1rem .6rem .1rem .1rem
.button-wrapper
float left
width 33.33%
.button
margin .1rem
padding .1rem 0
text-align center
border .02rem solid #ccc
border-radius .06rem
.item-list
.item
line-height .76rem
padding-left .2rem
</style>
c.编辑’City.vue’文件(路径: src/pages/city/Cityvue) - - - 监听事件
<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>
<script>
import axios from 'axios'
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
},
data () {
return {
cities: {},
hotCities: [],
letter: ''
}
},
// 定义这个方法
methods: {
getCityInfo () {
axios.get('/api/city.json')
.then(this.handleGetCityInfoSucc)
},
handleGetCityInfoSucc (res) {
// console.log(res)
res = res.data
if (res.ret && res.data) {
const data = res.data
this.cities = data.cities
this.hotCities = data.hotCities
}
},
handleLetterChange (letter) {
// console.log(letter)
this.letter = letter
}
},
// 创建一个生命周期函数来调用ajax的方法
mounted () {
this.getCityInfo()
}
}
</script>
<style lang="stylus" scoped>
</style>
7.兄弟组件数值传递 - - - 滚动字母表,城市列表相应滚动
a.编辑’Alphabet.vue’文件(路径: src/pages/city/Alphabet.vue)
<template>
<ul class="list">
<!-- 点击字母时,触发跳转事件 -->
<!-- v-for="(item, key) of cities" -->
<!-- :key="key" -->
<li
class="item"
v-for="item of letters"
:key="item"
:ref="item"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
@click="handleLetterClick"
>
<!-- {{key}} -->
{{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初始值为0
startY: 0,
// 设置timer为空
timer: null
}
},
// 创建一个生命周期钩子
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的操作频率,提高网页性能;
// 执行滚动操作时, 会延迟的16毫秒再执行;如果还在滚动, 则清除上一步操作, 执行新的操作
if (this.timer) {
clearTimeout(this.timer)
}
this.timer = setTimeout(() => {
// 性能问题: 因为startY是固定的,所以需要不断的获取它的值(可以用生命周期函数)
// 获取A元素距离顶部的高度
// const startY = this.$refs['A'][0].offsetTop
// 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.styl'
.list
display flex
flex-direction column
justify-content center
position absolute
top 1.58rem
bottom 0
right 0
width .4rem
// background red
.item
line-height .4rem
text-align center
color $bgColor
</style>
8.城市列表页面性能优化
<template>
<ul class="list">
<!-- 点击字母时,触发跳转事件 -->
<!-- v-for="(item, key) of cities" -->
<!-- :key="key" -->
<li
class="item"
v-for="item of letters"
:key="item"
:ref="item"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
@click="handleLetterClick"
>
<!-- {{key}} -->
{{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初始值为0
startY: 0,
// 设置timer为空
timer: null
}
},
// 创建一个生命周期钩子
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的操作频率,提高网页性能;
// 执行滚动操作时, 会延迟的16毫秒再执行;如果还在滚动, 则清除上一步操作, 执行新的操作
if (this.timer) {
clearTimeout(this.timer)
}
this.timer = setTimeout(() => {
// 性能问题: 因为startY是固定的,所以需要不断的获取它的值(可以用生命周期函数)
// 获取A元素距离顶部的高度
// const startY = this.$refs['A'][0].offsetTop
// 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.styl'
.list
display flex
flex-direction column
justify-content center
position absolute
top 1.58rem
bottom 0
right 0
width .4rem
// background red
.item
line-height .4rem
text-align center
color $bgColor
</style>
9.搜索逻辑实现
a.编辑’Search.vue’文件(路径: src/pages/city/Search.vue)
<template>
<div>
<div class="search">
<input
v-model="keyword"
class="search-input"
type="text"
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 { mapMutations } from 'vuex'
import BScroll from 'better-scroll'
export default {
name: 'CitySearch',
props: {
cities: Object
},
data () {
return {
keyword: '',
list: [],
timer: ''
}
},
methods: {
handleCityClick (city) {
this.changeCity(city)
this.$router.push('/')
},
...mapMutations(['changeCity'])
},
computed: {
hasNoData () {
return !this.list.length
}
},
watch: {
keyword () {
if (this.timer) {
clearTimeout(this.timer)
}
// 如果输入框清空,需要重新渲染数据
if (!this.keyword) {
this.list = []
return
}
this.timer = setTimeout(() => {
const result = []
for (let i in this.cities) {
this.cities[i].forEach((value) => {
if (value.spell.indexOf(this.keyword) > -1 ||
value.name.indexOf(this.keyword) > -1) {
result.push(value)
}
})
}
this.list = result
}, 100)
}
},
mounted () {
this.scroll = new BScroll(this.$refs.search, {
click: true
})
}
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.search
height .72rem
padding 0 .1rem
background $bgColor
.search-input
box-sizing border-box
width 100%
height .62rem
padding 0 .1rem
line-height .62rem
text-align center
border-radius .06rem
color #666
.search-content
z-index 1
overflow hidden
position absolute
top 1.58rem
left 0
right 0
bottom 0
background #eee
.search-item
line-height .62rem
padding-left .2rem
color #666
background #fff
</style>
#### b.编辑'City.vue'文件(路径: src/pages/city/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>
<script>
import axios from 'axios'
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
},
data () {
return {
cities: {},
hotCities: [],
letter: ''
}
},
// 定义这个方法
methods: {
getCityInfo () {
axios.get('/api/city.json')
.then(this.handleGetCityInfoSucc)
},
handleGetCityInfoSucc (res) {
// console.log(res)
res = res.data
if (res.ret && res.data) {
const data = res.data
this.cities = data.cities
this.hotCities = data.hotCities
}
},
handleLetterChange (letter) {
// console.log(letter)
this.letter = letter
}
},
// 创建一个生命周期函数来调用ajax的方法
mounted () {
this.getCityInfo()
}
}
</script>
<style lang="stylus" scoped>
</style>
9.Vuex实现数据共享1 - - - 选择城市后,首页的城市改变
a.原理
我们把公用的数据放到公用的空间去进行存储,某一个组件改动了公用数据,其他组件就能感知到
State: 驱动应用的数据源,我们所有的公用数据
Actions: 响应在 view 上的用户输入导致的状态变化; 组件去调用actions
Mutations: 一个个同步地对State的修改
b.安装vuex
npm install vuex --save
c.创建’store’文件夹和’index.js’文件(路径: src/store/index.js)
// 引用vue
import Vue from 'vue'
// 引用vuex
import Vuex from 'vuex'
// 引用state(简化index.js内的内容)
import state from './state'
// 引用mutations(简化index.js的内容)
import mutations from './mutations'
// 使用Vuex这个插件
Vue.use(Vuex)
// // 导出通过Vuex创建的仓库
// export default new Vuex.Store({
// state: {
// // 存放全局公用的数据
// // 默认展示武汉,选择后就用本地存储的城市
// city: localStorage.city || '武汉'
// },
// // 不涉及异步操作和批量操作,操作简单,所以可以跳过Actions
// // actions: {
// // changeCity (ctx, city) {
// // // console.log(city)
// // ctx.commit('changeCity', city)
// // }
// // },
// mutations: {
// changeCity (state, city) {
// state.city = city
// // 实现本地存储
// localStorage.city = city
// }
// }
// })
// 有些浏览器对于local的本地存储会报错,用更加规范的书写方式
// let defaultCity = '武汉'
// try {
// if (localStorage.city) {
// defaultCity = localStorage.city
// }
// } catch (e) {}
export default new Vuex.Store({
// state: {
// city: defaultCity
// },
// state: state,
state,
// mutations: {
// changeCity (state, city) {
// state.city = city
// try {
// localStorage.city = city
// } catch (e) {}
// }
// }
// mutations: mutations
mutations
// getters: {
// doubleCity (state) {
// return state.city + ' ' + state.city
// }
// }
})
d.编辑’main.js’文件(路径: src/main.js)
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
// 移动端30毫秒延迟问题
// import fastClick from 'fastClick'
// 引用轮播图插件
import VueAwesomeSwiper from 'vue-awesome-swiper'
// 引用通过Vuex创建的仓库Store
import store from './store'
// css样式
import 'styles/reset.css'
// 解决1px倍率问题
import 'styles/border.css'
// 引用iconfont的字体图标
import 'styles/iconfont.css'
// 引用轮播图插件的css样式
import 'swiper/dist/css/swiper.css'
Vue.config.productionTip = false
// fastClick.attach(document.body)
// 用轮播图插件
Vue.use(VueAwesomeSwiper)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
// 创建根目录实例
store,
components: { App },
template: '<App/>'
})
// 根据网址的不同,返回不同的内容给用户
e.编辑’Home.vue’文件(路径: src/pages/home/Home.js)
<template>
<!-- template只能向外暴露一个标签,所以需要在外面再套个盒子 -->
<div>
<!-- 引用HomeHeader组件 -->
<!-- <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>
import HomeHeader from './components/Header'
// 引用轮播图组件
import HomeSwiper from './components/Swiper'
// 引用icon(金刚区)组件
import HomeIcons from './components/Icons'
// 引用热销推荐
import HomeRecommend from './components/Recommend'
// 引用周末去哪儿
import HomeWeekend from './components/Weekend'
// 引用'axios'获取'ajix'请求
import axios from 'axios'
// 引用vuex
import {mapState} from 'vuex'
export default {
name: 'Home',
// 将注册的组件引用到home中来
components: {
HomeHeader,
HomeSwiper,
HomeIcons,
HomeRecommend,
HomeWeekend
},
// 所有数据
data () {
return {
// city: '',
swiperList: [],
iconList: [],
recommendList: [],
weekendList: [],
lastCity: []
}
},
computed: {
...mapState(['city'])
},
methods: {
getHomeInfo () {
// axios.get('/static/mock/index.json')
// 测试环境时候访问的本地'static/mock',上线时候访问的是'api'
// 切换城市后,需要根据选择的城市重新调数据
// axios.get('/api/index.json')
axios.get('/api/index.json?city=' + this.city)
.then(this.getHomeInfoSucc)
},
getHomeInfoSucc (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
}
// console.log(res)
}
},
mounted () {
this.lastCity = this.city
this.getHomeInfo()
// console.log('mounted')
},
activated () {
if (this.lastCity !== this.city) {
this.lastCity = this.city
this.getHomeInfo()
// console.log('activated')
}
}
}
</script>
<style>
</style>
f.编辑’Header.vue’文件(路径: src/pages/home/components/Header.vue)
<template>
<div class="header">
<div class="header-left">
<div class="iconfont back-icon">
</div>
</div>
<div class="header-input">
<span class="iconfont"></span>
输入城市/景点/游玩主题
</div>
<!-- 实现页面跳转 -->
<router-link to='/city'>
<div class="header-right">
<!-- 城市 -->
<!-- {{this.city}} -->
<!-- 通过前端mand.js传值,而不需要后端传值过来了 -->
<!-- {{this.$store.state.city}} -->
{{this.city}}
<!-- 可以通过getter的计算来获得新的数据 -->
<!-- {{this.doubleCity}} -->
<span class="iconfont arrow-icon"></span>
</div>
</router-link>
</div>
</template>
<script>
// import {mapState, mapGetters} from 'vuex'
import { mapState } from 'vuex'
export default {
name: 'HomeHeader',
// 子组件接收传值
// props: {
// // 切记string要大写,string是字符串的形式
// city: String
// }
// 把vuex里面的数据映射到computed计算属性里, 把city公用数组映射到city的计算属性中
// ...mapputed是展开运算符
computed: {
...mapState(['city'])
// ...mapGetters(['doubleCity'])
}
}
</script>
<style lang="stylus" scoped>
// 用'~'引用变量的样式
@import '~styles/varibles'
// @import '../../../assets/styles/varibles' @代表src目录 css中引用其他css样式需要用到'~'
.header
display: flex
line-height: $headerHight
color: #fff
background-color: $bgColor
// background-color: #00bcd4
.header-left
width: .64rem
float: left
.back-icon
text-align center
font-size .6rem
.header-input
flex: 1
margin-top: .12rem
margin-left: .2rem
padding-left .2rem
height: .64rem
line-height: .64rem
color: #ccc
border-radius: .1rem
background: #fff
.header-right
// width: 1.24rem
// 字符无论是几个字符都没问题了
min-width 1.04rem
padding 0 .1rem
float: right
text-align: center
// 修改字体颜色
color #fff
.arrow-icon
margin-left -.1rem
font-size .4rem
</style>
g.编辑’List.vue’文件(路径: src/pages/city/components/List.vue)
<template>
<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}} -->
{{this.currentCity}}
</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>
<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>
// 引入better-scroll
import BScroll from 'better-scroll'
import { mapState, mapMutations } from 'vuex'
export default {
name: 'CityList',
props: {
hot: Array,
cities: Object,
letter: String
},
computed: {
...mapState({
currentCity: 'city'
})
},
// methods: {
// handleCityClick (city) {
// // alert(city)
// // this.$store.dispatch('changeCity', city)
// // this.$store.commit('changeCity', city)
// this.changeCity(city)
// // 修改城市之后,跳转到首页
// this.$router.push('/')
// },
// ...mapMutations(['changeCity'])
// },
methods: {
handleCityClick (city) {
this.changeCity(city)
this.$router.push('/')
},
...mapMutations(['changeCity'])
},
// 侦听器 监听letter数据改变
watch: {
letter () {
if (this.letter) {
const element = this.$refs[this.letter][0]
// console.log(element)
this.scroll.scrollToElement(element)
}
// console.log(this.letter)
},
cities () {
this.$nextTick(function () {
this.scroll = new BScroll(this.$refs.wrapper, {
click: true,
mouseWheel: true,
tap: true,
disableMouse: false,
disableTouch: false
})
})
}
}
// 创建一个生命周期函数
// mounted () {
// // // 创建一个scroll实例
// // // this.scroll = new Bscroll(this.$refs.wrapper)
// // // console.log(BScroll)
// this.$nextTick(function () {
// this.scroll = new BScroll(this.$refs.wrapper, {
// click: true,
// mouseWheel: true,
// tap: true,
// disableMouse: false,
// disableTouch: false
// })
// })
// // this.scroll = new Bscroll(this.$refs.wrapper, {
// // click: true
// // })
// // this.scroll = new Bscroll(this.$refs.wrapper, {
// // click: true})
// }
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.border-topbottom
&:before
border-color #ccc
&:after
border-color #ccc
.border-bottom
&:before
border-color #ccc
.list
overflow hidden
position absolute
top 1.58rem
left 0
right 0
bottom 0
.title
line-height .54rem
color #666
font-size .26rem
padding-left .2rem
background #eee
.button-list
overflow hidden
padding .1rem .6rem .1rem .1rem
.button-wrapper
float left
width 33.33%
.button
margin .1rem
padding .1rem 0
text-align center
border .02rem solid #ccc
border-radius .06rem
.item-list
.item
line-height .76rem
padding-left .2rem
</style>
10.Vuex实现数据共享2 - - - 选择城市后,城市列表的当前城市发生改变
a.编辑’List.vue’文件(路径: src/pages/home/components/List.vue)
<template>
<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}} -->
{{this.currentCity}}
</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>
<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>
// 引入better-scroll
import BScroll from 'better-scroll'
import { mapState, mapMutations } from 'vuex'
export default {
name: 'CityList',
props: {
hot: Array,
cities: Object,
letter: String
},
computed: {
...mapState({
currentCity: 'city'
})
},
// methods: {
// handleCityClick (city) {
// // alert(city)
// // this.$store.dispatch('changeCity', city)
// // this.$store.commit('changeCity', city)
// this.changeCity(city)
// // 修改城市之后,跳转到首页
// this.$router.push('/')
// },
// ...mapMutations(['changeCity'])
// },
methods: {
handleCityClick (city) {
this.changeCity(city)
this.$router.push('/')
},
...mapMutations(['changeCity'])
},
// 侦听器 监听letter数据改变
watch: {
letter () {
if (this.letter) {
const element = this.$refs[this.letter][0]
// console.log(element)
this.scroll.scrollToElement(element)
}
// console.log(this.letter)
},
cities () {
this.$nextTick(function () {
this.scroll = new BScroll(this.$refs.wrapper, {
click: true,
mouseWheel: true,
tap: true,
disableMouse: false,
disableTouch: false
})
})
}
}
// 创建一个生命周期函数
// mounted () {
// // // 创建一个scroll实例
// // // this.scroll = new Bscroll(this.$refs.wrapper)
// // // console.log(BScroll)
// this.$nextTick(function () {
// this.scroll = new BScroll(this.$refs.wrapper, {
// click: true,
// mouseWheel: true,
// tap: true,
// disableMouse: false,
// disableTouch: false
// })
// })
// // this.scroll = new Bscroll(this.$refs.wrapper, {
// // click: true
// // })
// // this.scroll = new Bscroll(this.$refs.wrapper, {
// // click: true})
// }
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.border-topbottom
&:before
border-color #ccc
&:after
border-color #ccc
.border-bottom
&:before
border-color #ccc
.list
overflow hidden
position absolute
top 1.58rem
left 0
right 0
bottom 0
.title
line-height .54rem
color #666
font-size .26rem
padding-left .2rem
background #eee
.button-list
overflow hidden
padding .1rem .6rem .1rem .1rem
.button-wrapper
float left
width 33.33%
.button
margin .1rem
padding .1rem 0
text-align center
border .02rem solid #ccc
border-radius .06rem
.item-list
.item
line-height .76rem
padding-left .2rem
</style>
b.编辑’index.j’s’文件(路径: src/store/index.js)
// 引用vue
import Vue from 'vue'
// 引用vuex
import Vuex from 'vuex'
// 引用state(简化index.js内的内容)
import state from './state'
// 引用mutations(简化index.js的内容)
import mutations from './mutations'
// 使用Vuex这个插件
Vue.use(Vuex)
// // 导出通过Vuex创建的仓库
// export default new Vuex.Store({
// state: {
// // 存放全局公用的数据
// // 默认展示武汉,选择后就用本地存储的城市
// city: localStorage.city || '武汉'
// },
// // 不涉及异步操作和批量操作,操作简单,所以可以跳过Actions
// // actions: {
// // changeCity (ctx, city) {
// // // console.log(city)
// // ctx.commit('changeCity', city)
// // }
// // },
// mutations: {
// changeCity (state, city) {
// state.city = city
// // 实现本地存储
// localStorage.city = city
// }
// }
// })
// 有些浏览器对于local的本地存储会报错,用更加规范的书写方式
// let defaultCity = '武汉'
// try {
// if (localStorage.city) {
// defaultCity = localStorage.city
// }
// } catch (e) {}
export default new Vuex.Store({
// state: {
// city: defaultCity
// },
// state: state,
state,
// mutations: {
// changeCity (state, city) {
// state.city = city
// try {
// localStorage.city = city
// } catch (e) {}
// }
// }
// mutations: mutations
mutations
// getters: {
// doubleCity (state) {
// return state.city + ' ' + state.city
// }
// }
})
c.编辑’Search.vue’文件(路径: src/pages/home/components/Search.vue)
<template>
<div>
<div class="search">
<input
v-model="keyword"
class="search-input"
type="text"
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 { mapMutations } from 'vuex'
import BScroll from 'better-scroll'
export default {
name: 'CitySearch',
props: {
cities: Object
},
data () {
return {
keyword: '',
list: [],
timer: ''
}
},
methods: {
handleCityClick (city) {
this.changeCity(city)
this.$router.push('/')
},
...mapMutations(['changeCity'])
},
computed: {
hasNoData () {
return !this.list.length
}
},
watch: {
keyword () {
if (this.timer) {
clearTimeout(this.timer)
}
// 如果输入框清空,需要重新渲染数据
if (!this.keyword) {
this.list = []
return
}
this.timer = setTimeout(() => {
const result = []
for (let i in this.cities) {
this.cities[i].forEach((value) => {
if (value.spell.indexOf(this.keyword) > -1 ||
value.name.indexOf(this.keyword) > -1) {
result.push(value)
}
})
}
this.list = result
}, 100)
}
},
mounted () {
this.scroll = new BScroll(this.$refs.search, {
click: true
})
}
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.search
height .72rem
padding 0 .1rem
background $bgColor
.search-input
box-sizing border-box
width 100%
height .62rem
padding 0 .1rem
line-height .62rem
text-align center
border-radius .06rem
color #666
.search-content
z-index 1
overflow hidden
position absolute
top 1.58rem
left 0
right 0
bottom 0
background #eee
.search-item
line-height .62rem
padding-left .2rem
color #666
background #fff
</style>
d.Vue router - - - 编程式的导航
①. 编辑’Search.vue’文件(路径: src/pages/home/components/Search.vue)
methods: {
handleCityClick (city) {
this.changeCity(city)
this.$router.push('/')
},
...mapMutations(['changeCity'])
},
②. 编辑’List.vue’文件(路径: src/pages/home/components/List.vue)
methods: {
handleCityClick (city) {
this.changeCity(city)
this.$router.push('/')
},
...mapMutations(['changeCity'])
},
10.Vuex实现数据共享2(本地存储) - - - 选择城市后,刷新页面,依然展示上次选择的城市
a.编辑’index.js’文件(路径: src/store/index.js)
// 引用vue
import Vue from 'vue'
// 引用vuex
import Vuex from 'vuex'
// 引用state(简化index.js内的内容)
import state from './state'
// 引用mutations(简化index.js的内容)
import mutations from './mutations'
// 使用Vuex这个插件
Vue.use(Vuex)
// // 导出通过Vuex创建的仓库
// export default new Vuex.Store({
// state: {
// // 存放全局公用的数据
// // 默认展示武汉,选择后就用本地存储的城市
// city: localStorage.city || '武汉'
// },
// // 不涉及异步操作和批量操作,操作简单,所以可以跳过Actions
// // actions: {
// // changeCity (ctx, city) {
// // // console.log(city)
// // ctx.commit('changeCity', city)
// // }
// // },
// mutations: {
// changeCity (state, city) {
// state.city = city
// // 实现本地存储
// localStorage.city = city
// }
// }
// })
// 有些浏览器对于local的本地存储会报错,用更加规范的书写方式
// let defaultCity = '武汉'
// try {
// if (localStorage.city) {
// defaultCity = localStorage.city
// }
// } catch (e) {}
export default new Vuex.Store({
// state: {
// city: defaultCity
// },
// state: state,
state,
// mutations: {
// changeCity (state, city) {
// state.city = city
// try {
// localStorage.city = city
// } catch (e) {}
// }
// }
// mutations: mutations
mutations
// getters: {
// doubleCity (state) {
// return state.city + ' ' + state.city
// }
// }
})
b.创建’mutations.js’文件(路径: src/store/mutations.js)
export default {
changeCity (state, city) {
state.city = city
try {
localStorage.city = city
} catch (e) {}
}
}
c.创建’state.js’文件(路径: src/store/state.js)
let defaultCity = '武汉'
try {
if (localStorage.city) {
defaultCity = localStorage.city
}
} catch (e) {}
export default {
city: defaultCity
}
11.代码优化
a.编辑’Header.vue’文件(路径: src/pages/home/components/Header.vue)
<template>
<div class="header">
<div class="header-left">
<div class="iconfont back-icon">
</div>
</div>
<div class="header-input">
<span class="iconfont"></span>
输入城市/景点/游玩主题
</div>
<!-- 实现页面跳转 -->
<router-link to='/city'>
<div class="header-right">
<!-- 城市 -->
<!-- {{this.city}} -->
<!-- 通过前端mand.js传值,而不需要后端传值过来了 -->
<!-- {{this.$store.state.city}} -->
{{this.city}}
<!-- 可以通过getter的计算来获得新的数据 -->
<!-- {{this.doubleCity}} -->
<span class="iconfont arrow-icon"></span>
</div>
</router-link>
</div>
</template>
<script>
// import {mapState, mapGetters} from 'vuex'
import { mapState } from 'vuex'
export default {
name: 'HomeHeader',
// 子组件接收传值
// props: {
// // 切记string要大写,string是字符串的形式
// city: String
// }
// 把vuex里面的数据映射到computed计算属性里, 把city公用数组映射到city的计算属性中
// ...mapputed是展开运算符
computed: {
...mapState(['city'])
// ...mapGetters(['doubleCity'])
}
}
</script>
<style lang="stylus" scoped>
// 用'~'引用变量的样式
@import '~styles/varibles'
// @import '../../../assets/styles/varibles' @代表src目录 css中引用其他css样式需要用到'~'
.header
display: flex
line-height: $headerHight
color: #fff
background-color: $bgColor
// background-color: #00bcd4
.header-left
width: .64rem
float: left
.back-icon
text-align center
font-size .6rem
.header-input
flex: 1
margin-top: .12rem
margin-left: .2rem
padding-left .2rem
height: .64rem
line-height: .64rem
color: #ccc
border-radius: .1rem
background: #fff
.header-right
// width: 1.24rem
// 字符无论是几个字符都没问题了
min-width 1.04rem
padding 0 .1rem
float: right
text-align: center
// 修改字体颜色
color #fff
.arrow-icon
margin-left -.1rem
font-size .4rem
</style>
b.编辑’List.vue’文件(路径: src/pages/city/components/List.vue)
<template>
<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}} -->
{{this.currentCity}}
</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>
<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>
// 引入better-scroll
import BScroll from 'better-scroll'
import { mapState, mapMutations } from 'vuex'
export default {
name: 'CityList',
props: {
hot: Array,
cities: Object,
letter: String
},
computed: {
...mapState({
currentCity: 'city'
})
},
// methods: {
// handleCityClick (city) {
// // alert(city)
// // this.$store.dispatch('changeCity', city)
// // this.$store.commit('changeCity', city)
// this.changeCity(city)
// // 修改城市之后,跳转到首页
// this.$router.push('/')
// },
// ...mapMutations(['changeCity'])
// },
methods: {
handleCityClick (city) {
this.changeCity(city)
this.$router.push('/')
},
...mapMutations(['changeCity'])
},
// 侦听器 监听letter数据改变
watch: {
letter () {
if (this.letter) {
const element = this.$refs[this.letter][0]
// console.log(element)
this.scroll.scrollToElement(element)
}
// console.log(this.letter)
},
cities () {
this.$nextTick(function () {
this.scroll = new BScroll(this.$refs.wrapper, {
click: true,
mouseWheel: true,
tap: true,
disableMouse: false,
disableTouch: false
})
})
}
}
// 创建一个生命周期函数
// mounted () {
// // // 创建一个scroll实例
// // // this.scroll = new Bscroll(this.$refs.wrapper)
// // // console.log(BScroll)
// this.$nextTick(function () {
// this.scroll = new BScroll(this.$refs.wrapper, {
// click: true,
// mouseWheel: true,
// tap: true,
// disableMouse: false,
// disableTouch: false
// })
// })
// // this.scroll = new Bscroll(this.$refs.wrapper, {
// // click: true
// // })
// // this.scroll = new Bscroll(this.$refs.wrapper, {
// // click: true})
// }
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.border-topbottom
&:before
border-color #ccc
&:after
border-color #ccc
.border-bottom
&:before
border-color #ccc
.list
overflow hidden
position absolute
top 1.58rem
left 0
right 0
bottom 0
.title
line-height .54rem
color #666
font-size .26rem
padding-left .2rem
background #eee
.button-list
overflow hidden
padding .1rem .6rem .1rem .1rem
.button-wrapper
float left
width 33.33%
.button
margin .1rem
padding .1rem 0
text-align center
border .02rem solid #ccc
border-radius .06rem
.item-list
.item
line-height .76rem
padding-left .2rem
</style>
c.编辑’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"
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 { mapMutations } from 'vuex'
import BScroll from 'better-scroll'
export default {
name: 'CitySearch',
props: {
cities: Object
},
data () {
return {
keyword: '',
list: [],
timer: ''
}
},
methods: {
handleCityClick (city) {
this.changeCity(city)
this.$router.push('/')
},
...mapMutations(['changeCity'])
},
computed: {
hasNoData () {
return !this.list.length
}
},
watch: {
keyword () {
if (this.timer) {
clearTimeout(this.timer)
}
// 如果输入框清空,需要重新渲染数据
if (!this.keyword) {
this.list = []
return
}
this.timer = setTimeout(() => {
const result = []
for (let i in this.cities) {
this.cities[i].forEach((value) => {
if (value.spell.indexOf(this.keyword) > -1 ||
value.name.indexOf(this.keyword) > -1) {
result.push(value)
}
})
}
this.list = result
}, 100)
}
},
mounted () {
this.scroll = new BScroll(this.$refs.search, {
click: true
})
}
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.search
height .72rem
padding 0 .1rem
background $bgColor
.search-input
box-sizing border-box
width 100%
height .62rem
padding 0 .1rem
line-height .62rem
text-align center
border-radius .06rem
color #666
.search-content
z-index 1
overflow hidden
position absolute
top 1.58rem
left 0
right 0
bottom 0
background #eee
.search-item
line-height .62rem
padding-left .2rem
color #666
background #fff
</style>
d.编辑’store’文件(路径: src/store/store.js)
// 引用vue
import Vue from 'vue'
// 引用vuex
import Vuex from 'vuex'
// 引用state(简化index.js内的内容)
import state from './state'
// 引用mutations(简化index.js的内容)
import mutations from './mutations'
// 使用Vuex这个插件
Vue.use(Vuex)
// // 导出通过Vuex创建的仓库
// export default new Vuex.Store({
// state: {
// // 存放全局公用的数据
// // 默认展示武汉,选择后就用本地存储的城市
// city: localStorage.city || '武汉'
// },
// // 不涉及异步操作和批量操作,操作简单,所以可以跳过Actions
// // actions: {
// // changeCity (ctx, city) {
// // // console.log(city)
// // ctx.commit('changeCity', city)
// // }
// // },
// mutations: {
// changeCity (state, city) {
// state.city = city
// // 实现本地存储
// localStorage.city = city
// }
// }
// })
// 有些浏览器对于local的本地存储会报错,用更加规范的书写方式
// let defaultCity = '武汉'
// try {
// if (localStorage.city) {
// defaultCity = localStorage.city
// }
// } catch (e) {}
export default new Vuex.Store({
// state: {
// city: defaultCity
// },
// state: state,
state,
// mutations: {
// changeCity (state, city) {
// state.city = city
// try {
// localStorage.city = city
// } catch (e) {}
// }
// }
// mutations: mutations
mutations
// getters: {
// doubleCity (state) {
// return state.city + ' ' + state.city
// }
// }
})
e.编辑’Header.vue’文件(路径: src/pages/home/components/Header.vue)
<template>
<div class="header">
<div class="header-left">
<div class="iconfont back-icon">
</div>
</div>
<div class="header-input">
<span class="iconfont"></span>
输入城市/景点/游玩主题
</div>
<!-- 实现页面跳转 -->
<router-link to='/city'>
<div class="header-right">
<!-- 城市 -->
<!-- {{this.city}} -->
<!-- 通过前端mand.js传值,而不需要后端传值过来了 -->
<!-- {{this.$store.state.city}} -->
{{this.city}}
<!-- 可以通过getter的计算来获得新的数据 -->
<!-- {{this.doubleCity}} -->
<span class="iconfont arrow-icon"></span>
</div>
</router-link>
</div>
</template>
<script>
// import {mapState, mapGetters} from 'vuex'
import { mapState } from 'vuex'
export default {
name: 'HomeHeader',
// 子组件接收传值
// props: {
// // 切记string要大写,string是字符串的形式
// city: String
// }
// 把vuex里面的数据映射到computed计算属性里, 把city公用数组映射到city的计算属性中
// ...mapputed是展开运算符
computed: {
...mapState(['city'])
// ...mapGetters(['doubleCity'])
}
}
</script>
<style lang="stylus" scoped>
// 用'~'引用变量的样式
@import '~styles/varibles'
// @import '../../../assets/styles/varibles' @代表src目录 css中引用其他css样式需要用到'~'
.header
display: flex
line-height: $headerHight
color: #fff
background-color: $bgColor
// background-color: #00bcd4
.header-left
width: .64rem
float: left
.back-icon
text-align center
font-size .6rem
.header-input
flex: 1
margin-top: .12rem
margin-left: .2rem
padding-left .2rem
height: .64rem
line-height: .64rem
color: #ccc
border-radius: .1rem
background: #fff
.header-right
// width: 1.24rem
// 字符无论是几个字符都没问题了
min-width 1.04rem
padding 0 .1rem
float: right
text-align: center
// 修改字体颜色
color #fff
.arrow-icon
margin-left -.1rem
font-size .4rem
</style>
12.keep-alive 优化网页性能
a.编辑’App.vue’文件(路径: src/App.vue)
<template>
<div id="app">
<!-- 路由加载过一次之后,就把加载过的内容放到内存之中,下一次加载不需要重新渲染这个组件,直接从路由中调用 -->
<keep-alive exclude="Detail">
<!-- 显示当前路由地址所对应的内容 -->
<router-view/>
</keep-alive>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style></style>
b.编辑’index.js’文件(路径: src/store/index.js)
// 引用vue
import Vue from 'vue'
// 引用vuex
import Vuex from 'vuex'
// 引用state(简化index.js内的内容)
import state from './state'
// 引用mutations(简化index.js的内容)
import mutations from './mutations'
// 使用Vuex这个插件
Vue.use(Vuex)
// // 导出通过Vuex创建的仓库
// export default new Vuex.Store({
// state: {
// // 存放全局公用的数据
// // 默认展示武汉,选择后就用本地存储的城市
// city: localStorage.city || '武汉'
// },
// // 不涉及异步操作和批量操作,操作简单,所以可以跳过Actions
// // actions: {
// // changeCity (ctx, city) {
// // // console.log(city)
// // ctx.commit('changeCity', city)
// // }
// // },
// mutations: {
// changeCity (state, city) {
// state.city = city
// // 实现本地存储
// localStorage.city = city
// }
// }
// })
// 有些浏览器对于local的本地存储会报错,用更加规范的书写方式
// let defaultCity = '武汉'
// try {
// if (localStorage.city) {
// defaultCity = localStorage.city
// }
// } catch (e) {}
export default new Vuex.Store({
// state: {
// city: defaultCity
// },
// state: state,
state,
// mutations: {
// changeCity (state, city) {
// state.city = city
// try {
// localStorage.city = city
// } catch (e) {}
// }
// }
// mutations: mutations
mutations
// getters: {
// doubleCity (state) {
// return state.city + ' ' + state.city
// }
// }
})
#### c.编辑'Header.vue'文件(路径: src/pages/home/components/Header.vue)
<template>
<div class="header">
<div class="header-left">
<div class="iconfont back-icon">
</div>
</div>
<div class="header-input">
<span class="iconfont"></span>
输入城市/景点/游玩主题
</div>
<!-- 实现页面跳转 -->
<router-link to='/city'>
<div class="header-right">
<!-- 城市 -->
<!-- {{this.city}} -->
<!-- 通过前端mand.js传值,而不需要后端传值过来了 -->
<!-- {{this.$store.state.city}} -->
{{this.city}}
<!-- 可以通过getter的计算来获得新的数据 -->
<!-- {{this.doubleCity}} -->
<span class="iconfont arrow-icon"></span>
</div>
</router-link>
</div>
</template>
<script>
// import {mapState, mapGetters} from 'vuex'
import { mapState } from 'vuex'
export default {
name: 'HomeHeader',
// 子组件接收传值
// props: {
// // 切记string要大写,string是字符串的形式
// city: String
// }
// 把vuex里面的数据映射到computed计算属性里, 把city公用数组映射到city的计算属性中
// ...mapputed是展开运算符
computed: {
...mapState(['city'])
// ...mapGetters(['doubleCity'])
}
}
</script>
<style lang="stylus" scoped>
// 用'~'引用变量的样式
@import '~styles/varibles'
// @import '../../../assets/styles/varibles' @代表src目录 css中引用其他css样式需要用到'~'
.header
display: flex
line-height: $headerHight
color: #fff
background-color: $bgColor
// background-color: #00bcd4
.header-left
width: .64rem
float: left
.back-icon
text-align center
font-size .6rem
.header-input
flex: 1
margin-top: .12rem
margin-left: .2rem
padding-left .2rem
height: .64rem
line-height: .64rem
color: #ccc
border-radius: .1rem
background: #fff
.header-right
// width: 1.24rem
// 字符无论是几个字符都没问题了
min-width 1.04rem
padding 0 .1rem
float: right
text-align: center
// 修改字体颜色
color #fff
.arrow-icon
margin-left -.1rem
font-size .4rem
</style>
#### d.编辑'Home.vue'文件(路径: src/pages/home/Home.vue)
<template>
<!-- template只能向外暴露一个标签,所以需要在外面再套个盒子 -->
<div>
<!-- 引用HomeHeader组件 -->
<!-- <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>
import HomeHeader from './components/Header'
// 引用轮播图组件
import HomeSwiper from './components/Swiper'
// 引用icon(金刚区)组件
import HomeIcons from './components/Icons'
// 引用热销推荐
import HomeRecommend from './components/Recommend'
// 引用周末去哪儿
import HomeWeekend from './components/Weekend'
// 引用'axios'获取'ajix'请求
import axios from 'axios'
// 引用vuex
import {mapState} from 'vuex'
export default {
name: 'Home',
// 将注册的组件引用到home中来
components: {
HomeHeader,
HomeSwiper,
HomeIcons,
HomeRecommend,
HomeWeekend
},
// 所有数据
data () {
return {
// city: '',
swiperList: [],
iconList: [],
recommendList: [],
weekendList: [],
lastCity: []
}
},
computed: {
...mapState(['city'])
},
methods: {
getHomeInfo () {
// axios.get('/static/mock/index.json')
// 测试环境时候访问的本地'static/mock',上线时候访问的是'api'
// 切换城市后,需要根据选择的城市重新调数据
// axios.get('/api/index.json')
axios.get('/api/index.json?city=' + this.city)
.then(this.getHomeInfoSucc)
},
getHomeInfoSucc (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
}
// console.log(res)
}
},
mounted () {
this.lastCity = this.city
this.getHomeInfo()
// console.log('mounted')
},
activated () {
if (this.lastCity !== this.city) {
this.lastCity = this.city
this.getHomeInfo()
// console.log('activated')
}
}
}
</script>
<style>
</style>
e.编辑’App.vue’文件(路径: src/App.vue)
<template>
<div id="app">
<!-- 路由加载过一次之后,就把加载过的内容放到内存之中,下一次加载不需要重新渲染这个组件,直接从路由中调用 -->
<keep-alive exclude="Detail">
<!-- 显示当前路由地址所对应的内容 -->
<router-view/>
</keep-alive>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style></style>
#### d.编辑'Home.vue'文件(路径: src/pages/home/Home.vue)
<template>
<!-- template只能向外暴露一个标签,所以需要在外面再套个盒子 -->
<div>
<!-- 引用HomeHeader组件 -->
<!-- <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>
import HomeHeader from './components/Header'
// 引用轮播图组件
import HomeSwiper from './components/Swiper'
// 引用icon(金刚区)组件
import HomeIcons from './components/Icons'
// 引用热销推荐
import HomeRecommend from './components/Recommend'
// 引用周末去哪儿
import HomeWeekend from './components/Weekend'
// 引用'axios'获取'ajix'请求
import axios from 'axios'
// 引用vuex
import {mapState} from 'vuex'
export default {
name: 'Home',
// 将注册的组件引用到home中来
components: {
HomeHeader,
HomeSwiper,
HomeIcons,
HomeRecommend,
HomeWeekend
},
// 所有数据
data () {
return {
// city: '',
swiperList: [],
iconList: [],
recommendList: [],
weekendList: [],
lastCity: []
}
},
computed: {
...mapState(['city'])
},
methods: {
getHomeInfo () {
// axios.get('/static/mock/index.json')
// 测试环境时候访问的本地'static/mock',上线时候访问的是'api'
// 切换城市后,需要根据选择的城市重新调数据
// axios.get('/api/index.json')
axios.get('/api/index.json?city=' + this.city)
.then(this.getHomeInfoSucc)
},
getHomeInfoSucc (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
}
// console.log(res)
}
},
mounted () {
this.lastCity = this.city
this.getHomeInfo()
// console.log('mounted')
},
activated () {
if (this.lastCity !== this.city) {
this.lastCity = this.city
this.getHomeInfo()
// console.log('activated')
}
}
}
</script>
<style>
</style>
更多推荐
已为社区贡献7条内容
所有评论(0)