Vue去哪儿项目&城市选择页面&动态数据渲染


城市选择页面路由配置

城市页面路由配置

  1. 页面跳转

src\pages\home\components\Header.vue中 router-link to="/city"实现点击右上角页面跳转

1
2
3
4
5
6
<router-link to="/city">
<div class="header-right">
{{ this.city }}
<span class="iconfont arrow-cron">&#xe64a;</span>
</div>
</router-link>

这里router-link会使字体颜色发生变化,这是因为router-link在div外层加了个a标签,我们可以给header-right加一个颜色color:#fff

  1. src\pages\city\components\Header.vue代码实现

城市页面Header实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<template>
<div class="header">
城市选择
<router-link to="/">
<div class="iconfont header-back">&#xe624;</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: $headerHeight
line-height :$headerHeight
text-align:center
color:#fff
background :$bgColor
font-size:.32rem
.header-back
top:0
left:0
position:absolute
width 0.64rem
text-align:center
font-size :.4rem
color:#fff
</style>

  1. src\pages\city\City.vue引入使用上面的组件
1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<div>
<city-header></city-header>
</div>
</template>
<script>
import CityHeader from "./components/Header";
export default {
name: "City",
components: {
CityHeader,
},
}

搜索框布局

城市页面搜索框样式

src\pages\city\components\Search.vue代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<template>
<div class="search">
<input
v-model="keyword"
class="search-input"
type="text"
placeholder="输入城市名或拼音"
/>
</template>
<script>
export default {
name: "CitySearch",
}</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl';
.search
height:0.72rem
padding:0 .1rem
background:$bgColor
.search-input
box-sizing:border-box
width :100%
height: 0.62rem
padding:0 .1rem
line-height :.62rem
text-align :center
border-radius: 0.06rem
color:#666
.search-content
z-index:1
overflow :hidden
position:absolute
top: 1.58rem
right:0
left:0
bottom:0
background:#eee
.search-item
line-height :.62rem
padding-left :.2rem
color:#666
background:#fff
</style>

列表布局

城市列表

部分代码样式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<template>
<div class="list" ref="wrapper">
<div>
<div class="area">
<div class="title border-topbottom">当前城市</div>
<div class="buttom-list">
<div class="buttom-wrapper">
<div class="button">北京</div>
</div>
</div>
</div>
<div class="area">
<div class="title border-topbottom">热门城市</div>
<div class="buttom-list">
<div class="buttom-wrapper" v-for="item of hot" :key="item.id">
<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"
>
{{ innerItem.name }}
</div>
</div>
</div>
</div>
</div>
</template>

<style lang="stylus" scoped>
@import '~styles/varibles.styl';
.header
display:flex
line-height: $headerHeight
background: $bgColor
color: #fff
.header-left
width .64rem
float:left
.back-icon
text-align:center
font-size:.4rem
.header-input
flex:1
line-height:.64rem
height: .64rem
margin-top: .12rem
margin-left: .2rem
padding-left:.2rem
background: #fff
border-radius: .1rem
color:#ccc
.header-right
width: 1.24rem
float:right
text-align:center
color:#fff
.arrow-icon
margin-left :-.04rem
font-size :.24rem
</style>

城市列表

Better-scroll的使用及字母表布局

问题:列表布局中.list加了一个绝对定位和overflow:hidden这会导致页面是无法拖动的

解决:我们可以使用一个第三方的包Better-scroll

Github地址

  1. 安装
1
npm install better-scroll --save
  1. 使用(符合这个dom结构)

BetterScroll的最常见应用场景是列表滚动。让我们看看它的HTML:

1
2
3
4
5
6
7
8
<div class="wrapper">
<ul class="content">
<li>...</li>
<li>...</li>
...
</ul>
<!-- you can put some other DOMs here, it won't affect the scrolling
</div>
  1. 具体使用
1
import Bscroll from "better-scroll";
1
2
3
4
5
6
<div class="list" ref="wrapper">  //ref帮助我们获取该dom元素

//生命周期函数,载入后
mounted() {
this.scroll = new Bscroll(this.$refs.wrapper);
},
  1. 效果:上拉与下拉能够实现,并且有弹性动画效果,非常流畅

字母表布局

右侧字母表布局

  1. 创建组件src\pages\city\components\Alphabet.vue

部分代码样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
<ul class="list">
<li class="item" >
{{ item }}
</li>
</ul>
</template>
<script>
export default {
name: "CityAlphabet",
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl';
.list
display:flex
flex-direction :column
justify-content :center
position:absolute
top 1.58rem
right 0
bottom:0
width 0.4rem
.item
text-align:center
line-height :.4rem
color:$bgColor
</style>

城市列表页面动态数据渲染

利用ajax获取数据

  1. 准备好的本地模拟数据

数据

  1. ajax请求一般我们会放在最外层组件中获取,这样一次就能够获取到所有组件需要的内容

src\pages\city\City.vue这里我们在City.vue中发送

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<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="handLetterChange"></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
},
methods: {
getCityInfo() {
axios.get("/api/city.json").then(this.handleGetCityIngoSucc);
},
handleGetCityIngoSucc(res) {
res = res.data;
if (res.ret && res.data) {
const data = res.data;
this.cities = data.cities;
this.hotCities = data.hotCities;
}
},
handLetterChange(letter) {
// console.log(letter);
this.letter = letter;
}
},
// 存放数据
data() {
return {
cities: {},
hotCities: [],
letter: ""
};
},
// 生命周期函数
mounted() {
this.getCityInfo();
}
};
</script>
  1. 父组件向子组件传数据

例:

1
<city-list :cities="cities" :hot="hotCities" :letter="letter"></city-list>
  1. 子组件通过props接收
1
2
3
4
5
6
7
export default {
name: "CityList",
props: {
hot: Array,
cities: Object,
letter: String
},
  1. v-for渲染数据

循环数组

1
2
3
<div class="buttom-wrapper" v-for="item of hot" :key="item.id">
<div class="button">{{ item.name }}</div>
</div>

循环对象(这里我们使用了二次循环)

1
2
3
4
5
6
7
8
9
10
11
12
<div class="area" v-for="(item, key) of cities" :key="key" :ref="key">
<div class="title border-topbottom">{{ key }}</div>
<div class="item-list">
<div
class="item border-bottom"
v-for="innerItem of item"
:key="innerItem.id"
>
{{ innerItem.name }}
</div>
</div>
</div>