数据流转
修改路由src\router\index.js
:
······
{
path: '/shop/:id',
name: 'Shop',
component: () => import(/* webpackChunkName: "shop" */ '../views/shop/Shop.vue')
}
······
修改src\views\home\Nearby.vue
:
......
<router-link
v-for="(item, index) in nearbyList"
:key="index"
:to="`/shop/${item.id}`"
>
......
点击就会发现页面能够跳转详情页。
修改详情页代码,远程请求数据。src\views\shop\Shop.vue
:
<template>
<div class="wrapper">
<div class="search">
<div class="search__back" @click="handleBackClick">
<i class="search__back__icon custom-icon custom-icon-back"></i>
</div>
<div class="search__content">
<span
><i class="search__content__icon custom-icon custom-icon-search"></i
></span>
<input class="search__content__input" placeholder="请输入商品名称" />
</div>
</div>
<!-- v-show="item.headImg" 防止撕裂图片的出现 -->
<ShopInfo :item="item" :hideBorder="true" v-if="item.headImg" />
<Toast v-if="show" :message="message" />
</div>
</template>
<script>
import { reactive, toRefs, nextTick } from 'vue' // 路由跳转方法
import { useRouter, useRoute } from 'vue-router'
import ShopInfo from '@/components/ShopInfo/ShopInfo.vue'
import { get } from '@/utils/request.js'
import Toast, { useToastEffect } from '@/components/Toast/Toast'
const useShopInfoEffect = (toastMsg, route) => {
const data = reactive({ item: {} })
// eslint-disable-next-line no-unused-vars
const getItemData = async () => {
// 可以写成: const resultData = await get(`/api/shop/${route.params.id}`)
const resultData = await get('/api/shop/' + route.params.id)
if (resultData?.code === 200 && resultData?.data) {
data.item = {
id: resultData.data?.id,
title: resultData.data?.name,
sales: resultData.data?.sales,
headImg: resultData.data?.imgUrl,
expressLimit: resultData.data?.expressLimit,
expressPrice: resultData.data?.expressPrice,
highlight: resultData.data?.slogon
}
nextTick()
} else {
toastMsg('没有数据!')
}
}
const { item } = toRefs(data)
return { item, getItemData }
}
const useBackRouterEffect = router => {
const handleBackClick = () => {
router.back()
}
return { handleBackClick }
}
export default {
name: 'Shop',
components: { ShopInfo, Toast },
setup () {
const router = useRouter() // 整个大路由的信息
const route = useRoute() // 当前访问路径的信息
const { show, message, toastMsg } = useToastEffect()
const { item, getItemData } = useShopInfoEffect(toastMsg, route)
const { handleBackClick } = useBackRouterEffect(router)
getItemData()
return { show, message, item, handleBackClick }
}
}
</script>
新增src\views\shop\Content.vue
:
<template>
<div class="content">
<div class="category">
<div class="category__item category__item--active">全部商品</div>
<div class="category__item">折扣</div>
<div class="category__item">新鲜水果</div>
<div class="category__item">休闲食品</div>
<div class="category__item">时令蔬菜</div>
<div class="category__item">肉蛋家禽</div>
</div>
<div class="product">
<div class="product__item">
<img class="product__item__img" src="/i18n/9_16/img/tomato.png" />
<div class="product__item__detail">
<h4 class="product__item__title">番茄250g/份</h4>
<p class="product__item__sales">月售x件</p>
<p class="product__item__price">
<span class="product__item__yen">
¥33.6
</span>
<span class="product__item__origin">
¥66.6
</span>
</p>
</div>
<div class="product__number">
<span class="product__number__minus">-</span>
0
<span class="product__number__plus">+</span>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: ''
}
</script>
<style lang="scss" scoped>
@import '@/style/viriables.scss';
@import '@/style/mixins.scss';
.content {
display: flex;
position: absolute;
left: 0;
right: 0;
top: 1.6rem;
bottom: 0.5rem;
}
.category {
overflow-y: scroll;
width: 0.76rem;
background: $search-bg-color;
height: 100%;
&__item {
line-height: 0.4rem;
text-align: center;
font-size: 14px;
color: $content-font-color;
&--active {
background: $bg-color;
}
}
}
.product {
overflow-y: scroll;
flex: 1;
&__item {
position: relative;
display: flex;
padding: 0.12rem 0.16rem;
margin: 0 0.16rem;
border-bottom: 0.01rem solid $content-bg-color;
// 配合解决超出长度以省略号显示而不会出现换行
&__detail {
overflow: hidden;
}
&__img {
width: 0.68rem;
height: 0.68rem;
margin-right: 0.16rem;
}
&__title {
margin: 0;
line-height: 0.2rem;
font-size: 0.14rem;
color: $content-font-color;
// 超出长度以省略号显示而不会出现换行
@include ellipsis;
}
&__sales {
margin: 0.06rem 0;
line-height: 0.16rem;
font-size: 0.12rem;
color: $content-font-color;
}
&__price {
margin: 0;
line-height: 0.2rem;
font-size: 0.14rem;
color: $height-light-font-color;
}
&__yen {
font-size: 0.12rem;
}
&__origin {
margin-left: 0.06rem;
line-height: 0.2rem;
font-size: 0.12rem;
color: $light-font-color;
text-decoration: line-through; //中划线
}
// 购物车选购数量和加减号
.product__number {
position: absolute;
right: 0rem;
bottom: 0.12rem;
&__minus,
&__plus {
display: inline-block;
width: 0.2rem;
height: 0.2rem;
line-height: 0.16rem;
border-radius: 50%;
font-size: 0.2rem;
text-align: center;
}
// 边框白色
&__minus {
border: 0.01rem solid $medium-font-color;
color: $medium-font-color;
margin-right: 0.05rem;
}
//无边框,背景蓝色
&__plus {
color: $bg-color;
background: $btn-bg-color;
margin-left: 0.05rem;
}
}
}
}
</style>
优化全局,替换css:src\style\viriables.scss
:
/**
* 内容主体文字颜色
**/
$content-font-color: #333;
/**
* 无内容、背景灰、留白灰的颜色
**/
$content-bg-color: #f1f1f1;
/**
* 文字灰色字体
*
**/
$content-notice-font-color: #777;
/**
* 搜索框的背景色
**/
$search-bg-color: #f5f5f5;
/**
* 搜索框内文字颜色
**/
$search-font-color: #b7b7b7;
/**
* 默认背景颜色
**/
$bg-color: #fff;
/**
* 亮色主题高亮文字颜色
**/
$height-light-font-color: #e83b3b;
/**
* 中亮文字颜色
**/
$medium-font-color: #666;
/**
* 亮文字颜色
**/
$light-font-color: #999;
/**
* 按钮背景颜色
**/
$btn-bg-color: #0091ff;
优化stop.vue
<template>
<div class="wrapper">
<div class="search">
<div class="search__back" @click="handleBackClick">
<i class="search__back__icon custom-icon custom-icon-back"></i>
</div>
<div class="search__content">
<span
><i class="search__content__icon custom-icon custom-icon-search"></i
></span>
<input class="search__content__input" placeholder="请输入商品名称" />
</div>
</div>
<!-- v-show="item.headImg" 防止撕裂图片的出现 -->
<ShopInfo :item="item" :hideBorder="true" v-if="item.headImg" />
<Content />
<Toast v-if="show" :message="message" />
</div>
</template>
<script>
import { reactive, toRefs, nextTick } from 'vue' // 路由跳转方法
import { useRouter, useRoute } from 'vue-router'
import ShopInfo from '@/components/ShopInfo/ShopInfo'
import { get } from '@/utils/request.js'
import Toast, { useToastEffect } from '@/components/Toast/Toast'
import Content from '@/views/shop/Content'
// 获取当前商铺信息
const useShopInfoEffect = (toastMsg, route) => {
const data = reactive({ item: {} })
// eslint-disable-next-line no-unused-vars
const getItemData = async () => {
// 可以写成: const resultData = await get(`/api/shop/${route.params.id}`)
console.log(' route.params.id:' + route.params.id)
const resultData = await get('/api/shop/' + route.params.id)
if (resultData?.code === 200 && resultData?.data) {
data.item = {
id: resultData.data?.id,
title: resultData.data?.name,
sales: resultData.data?.sales,
headImg: resultData.data?.imgUrl,
expressLimit: resultData.data?.expressLimit,
expressPrice: resultData.data?.expressPrice,
highlight: resultData.data?.slogon
}
console.log('data.item :' + JSON.stringify(data.item))
debugger
nextTick()
} else {
toastMsg('没有数据!')
}
}
const { item } = toRefs(data)
return { item, getItemData }
}
// 后退按钮事件
const useBackRouterEffect = router => {
const handleBackClick = () => {
router.back()
}
return { handleBackClick }
}
export default {
name: 'Shop',
components: { ShopInfo, Toast, Content },
// eslint-disable-next-line space-before-function-paren
setup() {
const router = useRouter() // 整个大路由的信息
const route = useRoute() // 当前访问路径的信息
const { show, message, toastMsg } = useToastEffect()
const { item, getItemData } = useShopInfoEffect(toastMsg, route)
const { handleBackClick } = useBackRouterEffect(router)
getItemData()
return { show, message, item, handleBackClick }
}
}
</script>
<style lang="scss" scoped>
@import '@/style/viriables';
.wrapper {
padding: 0 0.18rem;
}
.search {
margin: 0.14rem 0 0.04rem 0;
display: flex;
line-height: 0.32rem; //高度会将父元素撑开
&__back {
width: 0.3rem;
&__icon {
font-size: 0.2rem;
color: #b6b6b6;
}
}
&__content {
display: flex;
flex: 1;
background: $search-bg-color;
border-radius: 0.16rem;
&__icon {
padding-left: 0.1rem;
padding-right: 0.1rem;
width: 0.44rem;
text-align: center;
color: $search-font-color;
}
&__input {
padding-right: 0.2rem;
width: 100%;
display: block;
border: none;
outline: none;
background: none;
height: 0.32rem;
font-size: 0.14rem;
color: $content-font-color;
&::placeholder {
color: $content-font-color;
}
}
}
}
</style>
结果如下:
其中接口
/mock/api/shop/:id
:
数据如下:
{
"code": 200,
"data": {
"id": "1",
"name": "某什么玛1",
"imgUrl": "/i18n/9_16/img/near.png",
"sales": 200,
"expressLimit": 0,
"expressPrice": 5,
"slogon": "VIP尊享xx元减x元运费券(每月x张)"
},
"desc": "成功"
}