【vue3.0】12.0 某东到家(十二)——商家详情页开发(二)

数据流转

修改路由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">
              &yen;33.6
            </span>
            <span class="product__item__origin">
              &yen;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>

结果如下:

image.png

其中接口/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": "成功"
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容