Fork me on GitHub
余鸢

饿了么45个页面重构(十):router传参和详情页面开发

商品详情页

设置商品的router,点击商品展示商品详情页,设置传递参数。

在router.js中设置路由映射。

1
2
3
4
5
6
7
8
9
10
{
path: '/shop',
component: Shop, // 商铺详情页
children: [
{
path: 'foodDetail', // 食品详情页
component: FoodDetail
}
]
},

router传参

传参是前端经常需要用的一个操作,很多场景都会需要用到上个页面的参数。Vue router使用query和params传参,当你使用params方法传参的时候,要在路由后面加参数名,并且传参的时候,参数名要跟路由后面设置的参数名对应。使用query方法,就没有这种限制,直接在跳转里面用就可以。

例如:

params:/router1/:id ,/router1/123,/router1/789 ,这里的id叫做params

query:/router1?id=123 ,/router1?id=456 ,这里的id叫做query。

query更加类似于我们ajax中get传参,params则类似于post,说的再简单一点,前者在浏览器地址栏中显示参数,后者则不显示。

在这里我使用query传参。

shop.vue

1
2
3
4
5
6
7
<section v-for="(food, foodIndex) in item.foods" :key="foodIndex" class="menu_detail_list">
<router-link :to="{path: 'shop/foodDetail',
query: {image_path: food.image_path, description: food.description, month_sales: food.month_sales, name: food.name, rating: food.rating, rating_count: food.rating_count, satisfy_rate: food.satisfy_rate, food, shopId}}"
tag="div"
class="menu_detail_link"
></router-link>
</section>

页面转跳之后通过router特性获取上页传递过来的参数,同时data中设置一些数据。

foodDetail.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
data () {
return {
goBack: true,
image_path: null,
description: null,
month_sales: null,
name: null,
rating: null,
rating_count: null,
satisfy_rate: null,
food: null,
shopId: null
}
},
created () {
this.image_path = this.$route.query.image_path
this.description = this.$route.query.description
this.month_sales = this.$route.query.month_sales
this.name = this.$route.query.name
this.rating = this.$route.query.rating
this.rating_count = this.$route.query.rating_count
this.satisfy_rate = this.$route.query.satisfy_rate
this.food = this.$route.query.food
this.shopId = this.$route.query.shopId
},

设置商品图片:<img :src="getImgPath(image_path)" class="food_img">

设置商品描述:<p class="description"></p>

设置商品名称和评分

1
2
3
4
5
6
<p>{{name}}</p>
<div class="rating_sale">
<span>评分</span>
<rating-star :rating="rating"></rating-star>
<span>{{rating.toFixed(1)}}</span>
</div>

设置月售单量和售价

1
2
3
4
5
<p>
<span>月售{{month_sales}}单</span>
<span>售价 ¥{{food.specfoods[0].price}}</span>
<span v-if="food.specfoods.length">起</span>
</p>

设置评论数和好评率

1
2
3
4
<p>
<span>评论数 {{rating_count}}</span>
<span>好评率 {{satisfy_rate}}%</span>
</p>

效果如图:

e27

餐厅详情页

在router.js中设置路由映射。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
path: '/shop',
component: Shop, // 商铺详情页
children: [
{
path: 'foodDetail', // 食品详情页
component: FoodDetail
},
{
path: 'shopDetail', //商铺详情页
component: ShopDetail,
}
]
},

点击店铺公告转跳餐厅详情页面,设置路由

1
<router-link to="/shop/shopDetail" class="description_top"></router-link>

在shop.vue组件中获取到商家详情信息并通过vuex管理对数据做处理。

state.js

1
2
3
const state = {
shopDetail: null
}

mutation-types.js

1
export const RECORD_SHOPDETAIL = 'RECORD_SHOPDETAIL'

mutations.js

1
2
3
[types.RECORD_SHOPDETAIL] (state, detail) {
state.shopDetail = detail
},

shop.vue

1
2
3
4
5
6
7
8
9
10
11
created: {
shopDetails(this.shopId, this.extras, this.latitude, this.longitude).then(res => {
this.shopDetailData = res
this.img = res.image_path
this.RECORD_SHOPDETAIL(this.shopDetailData)
})
}
...mapMutations([
'RECORD_SHOPDETAIL'
])

通过this.RECORD_SHOPDETAIL(this.shopDetailData)记录商家详情信息,在shopDetail.vue组件中通过mapState获取商家详情信息。

1
2
3
4
5
computed: {
...mapState([
'shopDetail'
])
},

接着填充dom

设置属性:

1
2
3
4
5
6
7
<header>活动与属性</header>
<ul class="activities_ul">
<li v-for="item in shopDetail.activities" :key="item.id">
<span :style="{backgroundColor: '#' + item.icon_color}">{{item.icon_name}}</span>
<span>{{item.description}}(APP专享)</span>
</li>
</ul>

设置活动:

1
2
3
4
5
6
<ul class="activities_ul">
<li v-for="item in shopDetail.supports" :key="item.id">
<span :style="{backgroundColor: '#' + item.icon_color}">{{item.icon_name}}</span>
<span>{{item.description}}(APP专享)</span>
</li>
</ul>

设置监督检查结果,使用v-if和v-else判断它的状态显示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<section class="shop_status_detail">
<div>
<svg class="shop_status" v-if="shopDetail.status == 1">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#res-well"></use>
</svg>
<svg class="res-well" v-else>
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#res-bad"></use>
</svg>
</div>
<div class="check_date">
<p>
<span>监督检查结果:</span>
<span class="shop_status_well" v-if="shopDetail.status == 1">良好</span>
<span class="shop_status_bad" v-else>差</span>
</p>
</div>
</section>

设置商家信息:

1
2
3
4
5
6
<section class="shop_status_info">
<header>商家信息</header>
<p>{{shopDetail.name}}</p>
<p>地址:{{shopDetail.address}}</p>
<p>营业时间:[{{shopDetail.opening_hours[0]}}]</p>
</section>

食品监督安全公示

router.js中设置路由映射。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
path: '/shop',
component: Shop, // 商铺详情页
children: [
{
path: 'foodDetail', // 食品详情页
component: FoodDetail
},
{
path: 'shopDetail', //商铺详情页
component: ShopDetail,
children: [
{
path: 'shopSafe', //商铺安全认证页
component: ShopSafe
}
]
}
]
},

设置路由跳转

1
<router-link :to="{path: '/shop/shopDetail/shopSafe', query: {restaurant_id: shopDetail.id}}" class="shop_status_header"></router-link>

具体代码很简单就不传了。

效果如图:

e28

总结:

到这整个shop.vue组件全部开发完毕!组件中运用不少v-if也讲了v-if与v-show的区别,以及router传参方式。Vue在插入、更新或者移除DOM元素时会应用过渡效果,文中用到初始渲染的过渡,自定义过渡钩子函数利用JavaScript的方式直接操作DOM。数据处理上我使用vuex对购物车所有数据做统一管理,使整个数据流更加清晰。

具体代码见:

https://github.com/kakajing/vue-elmm

如有什么疑问或者不懂之处,可以加这个群交流:

QQ群:157028081