Vue3电商项目实战-商品详情模块1【01-商品详情-基础布局、02-商品详情-渲染面包屑、03-商品详情-图片预览组件、04-商品详情-图片放大镜】

news2024/9/20 14:42:50

文章目录

    • 01-商品详情-基础布局
    • 02-商品详情-渲染面包屑
    • 03-商品详情-图片预览组件
    • 04-商品详情-图片放大镜


01-商品详情-基础布局

目的:完成商品详情基础布局,路由配置,搭好页面架子。

在这里插入图片描述

大致步骤:

  • 准备组件结构容器
  • 提取商品推荐组件且使用
  • 配置路由和组件

落地代码:

  • 页面组件:src/views/goods/index.vue
<template>
  <div class='xtx-goods-page'>
    <div class="container">
      <!-- 面包屑 -->
      <XtxBread>
        <XtxBreadItem to="/">首页</XtxBreadItem>
        <XtxBreadItem to="/">手机</XtxBreadItem>
        <XtxBreadItem to="/">华为</XtxBreadItem>
        <XtxBreadItem to="/">p30</XtxBreadItem>
      </XtxBread>
      <!-- 商品信息 -->
      <div class="goods-info"></div>
      <!-- 商品推荐 -->
      <GoodsRelevant />
      <!-- 商品详情 -->
      <div class="goods-footer">
        <div class="goods-article">
          <!-- 商品+评价 -->
          <div class="goods-tabs"></div>
          <!-- 注意事项 -->
          <div class="goods-warn"></div>
        </div>
        <!-- 24热榜+专题推荐 -->
        <div class="goods-aside"></div>
      </div>
    </div>
  </div>
</template>

<script>
import GoodsRelevant from './components/goods-relevant'
export default {
  name: 'XtxGoodsPage',
  components: { , GoodsRelevant }
}
</script>

<style scoped lang='less'>
.goods-info {
  min-height: 600px;
  background: #fff;
}
.goods-footer {
  display: flex;
  margin-top: 20px;
  .goods-article {
    width: 940px;
    margin-right: 20px;
  }
  .goods-aside {
    width: 280px;
    min-height: 1000px;
  }
}
.goods-tabs {
  min-height: 600px;
  background: #fff;
}
.goods-warn {
  min-height: 600px;
  background: #fff;
  margin-top: 20px;
}
</style>
  • 商品推荐组件:src/views/goods/components/goods-relevant.vue
<template>
  <div class='goods-relevant'></div>
</template>

<script>
export default {
  name: 'GoodsRelevant'
}
</script>

<style scoped lang='less'>
.goods-relevant {
  background: #fff;
  min-height: 460px;
  margin-top: 20px;
}
</style>
  • 路由配置:src/router/index.js
const Goods = () => import('@/views/goods/index')
    children: [
      { path: '/', component: Home },
      { path: '/category/:id', component: TopCategory },
      { path: '/category/sub/:id', component: SubCategory },
+      { path: '/product/:id', component: Goods }
    ]

02-商品详情-渲染面包屑

目的:获取数据,渲染面包屑。

大致步骤:

  • 定义获取商品详情API函数
  • 在组件setup中获取商品详情数据
  • 定义一个useXxx函数处理数据

落地代码:

  • API函数 src/api/product.js
import request from '@/utils/request'

/**
 * 获取商品详情
 * @param {String} id - 商品ID
 */
export const findGoods = (id) => {
  return request('/goods', 'get', { id })
}
  • useGoods函数 src/views/goods/index.vue 在setup中使用
import GoodsRelevant from './components/goods-relevant'
import { nextTick, ref, watch } from 'vue'
import { findGoods } from '@/api/product'
import { useRoute } from 'vue-router'
export default {
  name: 'XtxGoodsPage',
  components: { GoodsRelevant },
  setup () {
    const goods = useGoods()
    return { goods }
  }
}
// 获取商品详情
const useGoods = () => {
  // 出现路由地址商品ID发生变化,但是不会重新初始化组件
  const goods = ref(null)
  const route = useRoute()
  watch(() => route.params.id, (newVal) => {
    if (newVal && `/product/${newVal}` === route.path) {
      findGoods(route.params.id).then(data => {
        // 让商品数据为null让后使用v-if的组件可以重新销毁和创建
        goods.value = null
        nextTick(() => {
          goods.value = data.result
        })
      })
    }
  }, { immediate: true })
  return goods
}
  • 防止报错,加载完成goods再显示所有内容
<div class='xtx-goods-page' v-if="goods">
  • 渲染面包屑
      <!-- 面包屑 -->
      <XtxBread>
        <XtxBreadItem to="/">首页</XtxBreadItem>
        <XtxBreadItem :to="'/category/'+goods.categories[0].id">{{goods.categories[0].name}}</XtxBreadItem>
        <XtxBreadItem :to="'/category/sub/'+goods.categories[1].id">{{goods.categories[1].name}}</XtxBreadItem>
        <XtxBreadItem>{{goods.name}}</XtxBreadItem>
      </XtxBread>

03-商品详情-图片预览组件

目的:完成商品图片预览功能和切换

在这里插入图片描述

大致步骤:

  • 首先准备商品信息区块左右两侧的布局盒子
  • 在定义一个商品图片组件,用来实现图片预览
    • 首先组件布局,渲染
    • 实现切换图片

落地代码:

  • 商品信息区块,布局盒子 src/views/goods/index.vue
      <!-- 商品信息 -->
      <div class="goods-info">
        <div class="media"></div>
        <div class="spec"></div>
      </div>
.goods-info {
  min-height: 600px;
  background: #fff;
  display: flex;
  .media {
    width: 580px;
    height: 600px;
    padding: 30px 50px;
  }
  .spec {
    flex: 1;
    padding: 30px 30px 30px 0;
  }
}
  • 商品图片组件,渲染和切换
<template>
  <div class="goods-image">
    <div class="middle">
      <img :src="images[currIndex]" alt="">
    </div>
    <ul class="small">
      <li v-for="(img,i) in images" :key="img" :class="{active:i===currIndex}">
        <img @mouseenter="currIndex=i" :src="img" alt="">
      </li>
    </ul>
  </div>
</template>
<script>
import { ref } from 'vue'
export default {
  name: 'GoodsImage',
  props: {
    images: {
      type: Array,
      default: () => []
    }
  },
  setup (props) {
    const currIndex = ref(0)
    return { currIndex }
  }
}
</script>
<style scoped lang="less">
.goods-image {
  width: 480px;
  height: 400px;
  position: relative;
  display: flex;
  .middle {
    width: 400px;
    height: 400px;
    background: #f5f5f5;
  }
  .small {
    width: 80px;
    li {
      width: 68px;
      height: 68px;
      margin-left: 12px;
      margin-bottom: 15px;
      cursor: pointer;
      &:hover,&.active {
        border: 2px solid @xtxColor;
      }
    }
  }
}
</style>

04-商品详情-图片放大镜

目的:实现图片放大镜功能

在这里插入图片描述

大致步骤:

  • 首先准备大图容器和遮罩容器
  • 然后使用@vueuse/coreuseMouseInElement方法获取基于元素的偏移量
  • 计算出 遮罩容器定位与大容器北京定位 暴露出数据给模板使用

落地代码:src/views/goods/components/goods-image.vue

  • 准备大图容器
  <div class='goods-image'>
+    <div class="large" :style="[{backgroundImage:`url(${images[currIndex]})`}]"></div>
    <div class="middle">
.goods-image {
  width: 480px;
  height: 400px;
  position: relative;
  display: flex;
+  z-index: 500;
+  .large {
+    position: absolute;
+    top: 0;
+    left: 412px;
+    width: 400px;
+    height: 400px;
+    box-shadow: 0 0 10px rgba(0,0,0,0.1);
+    background-repeat: no-repeat;
+    background-size: 800px 800px;
+    background-color: #f8f8f8;
+  }
  • 准备待移动的遮罩容器
    <div class="middle" ref="target">
      <img :src="images[currIndex]" alt="">
+      <div class="layer"></div>
    </div>
  .middle {
    width: 400px;
    height: 400px;
+    position: relative;
+    cursor: move;
+    .layer {
+      width: 200px;
+      height: 200px;
+      background: rgba(0,0,0,.2);
+      left: 0;
+      top: 0;
+      position: absolute;
+    }
  }
  • 使用vueuse提供的API获取鼠标偏移量
import { reactive, ref, watch } from 'vue'
import { useMouseInElement } from '@vueuse/core'
const usePreviewImg = () => {
  const target = ref(null)
  const show = ref(false)
  // elementX 鼠标基于容器左上角X轴偏移
  // elementY 鼠标基于容器左上角Y轴偏移
  // isOutside 鼠标是否在模板容器外
  const { elementX, elementY, isOutside } = useMouseInElement(target)
  const position = reactive({ left: 0, top: 0 })
  const bgPosition = reactive({ backgroundPositionX: 0, backgroundPositionY: 0 })
  watch([elementX, elementY, isOutside], () => {
    // 控制X轴方向的定位 0-200 之间
    if (elementX.value < 100) position.left = 0
    else if (elementX.value > 300) position.left = 200
    else position.left = elementX.value - 100
    // 控制Y轴方向的定位 0-200 之间
    if (elementY.value < 100) position.top = 0
    else if (elementY.value > 300) position.top = 200
    else position.top = elementY.value - 100
    // 设置大背景的定位
    bgPosition.backgroundPositionX = -position.left * 2 + 'px'
    bgPosition.backgroundPositionY = -position.top * 2 + 'px'
    // 设置遮罩容器的定位
    position.left = position.left + 'px'
    position.top = position.top + 'px'
    // 设置是否显示预览大图
    show.value = !isOutside.value
  })
  return { position, bgPosition, show, target }
}
  • 在setup中返回模板需要数据,并使用它
  setup () {
    const { currIndex, toggleImg } = useToggleImg()
+    const { position, bgPosition, show, target } = usePreviewImg()
+    return { currIndex, toggleImg, position, bgPosition, show, target }
  }
    <div class="large" v-show="show" :style="[{backgroundImage:`url(${images[currIndex]})`},bgPosition]"></div>
    <div class="middle" ref="target">
      <img :src="images[currIndex]" alt="">
      <div class="layer" v-show="show" :style="position"></div>
    </div>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/358825.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

十二月券商金工精选

✦研报目录✦ ✦简述✦ 按发布时间排序 华宝证券 主动暴露的得与失—从Barra框架到私募指增因子分析方法 发布日期&#xff1a;2022-12-01 关键词&#xff1a;股票、Barra、风险暴露、指数增强 主要内容&#xff1a;本文针对私募指数增强产品的策略流程&#xff0c;设计…

<JVM上篇:内存与垃圾回收篇>11 - 垃圾回收相关算法

对象存活判断 在堆里存放着几乎所有的 Java 对象实例&#xff0c;在 GC 执行垃圾回收之前&#xff0c;首先需要区分出内存中哪些是存活对象&#xff0c;哪些是已经死亡的对象。只有被标记为己经死亡的对象&#xff0c;GC 才会在执行垃圾回收时&#xff0c;释放掉其所占用的内存…

vue项目开发(vue2与vue3对比)

vue中使用typescrip 初与typescrip的约定情愫&#xff1a;最近项目要用到vue3,所以打算使用typescrip语法&#xff01; 安装&#xff1a; npx tyarn add typescript vue/cli-plugin-typescript -D npx tsc --init修改 tsconfig.json&#xff1a; {"compilerOptions&quo…

LVS中的keepalived高可用

文章目录前言一、Keepalived简介二、keepalived工作原理三、配置文件四、实验1.某台Real Server down2.LVS本身down实验过程&#xff1a;五、代码详细演示整体过程调度器安装软件、设置测试keepalived对后端RS的健康检测backup服务主机设置前言 一、Keepalived简介 Keepalived是…

ubuntu18.4安装Redmine软件

1.github网站下载Redmine4.2.0的安装包&#xff0c;如下图所示&#xff1a; https://github.com/redmine/redmine/releases/tag/4.2.0 图1 github网站下载redmine4.2.0安装包2.拷贝Redmine4.2.0的安装包到ubuntu工作目录&#xff0c;并解压缩&#xff0c;如下所示&#xff1a;…

Springboot前后端分离国际化实现-chatgpt

前言 Springboot国际化可以帮助使用者在不同语言环境中构建应用程序&#xff0c;这样应用程序可以有效地适应不同语言文化背景下的用户需求。 此外&#xff0c;Springboot国际化也可以方便多语言应用程序重用和维护&#xff0c;从而减少了系统部署的时间成本和维护的费用。 要实…

医疗方案 | 星辰天合入选“2022智慧新医信优秀解决方案”

近日&#xff0c;由 HC3i数字医疗网主办的《数字化转型驱动下的医院高质量发展论坛》暨 2022 智慧新医信优秀解决方案发布仪式在线上召开。XSKY星辰天合的“智慧医疗软件定义数据基础设施”解决方案成功入选 2022 智慧新医信优秀解决方案&#xff0c;。此次论坛由 HC3i 数字医疗…

会利用信息差赚钱的人才是聪明人

毕业后找不到工作&#xff0c;穷到只剩下时间&#xff0c;大小做了20多份副业兼职&#xff0c;终于找到了可靠的渠道&#xff0c; 我是专科生&#xff0c;学历不好&#xff0c;专业拉胯。毕业后&#xff0c;我找了两三份工作。要么工资太低&#xff0c;只能交房租&#xff0c;…

javaFx实现鼠标穿透画布,同时操作画布和桌面,背景透明,类似ppt批注

一、功能需要由来和大致效果 今天&#xff0c;我们要用javaFx来实现一个鼠标穿透画布的功能&#xff0c;该需求来自于在我们的javaFx桌面应用中&#xff0c;需要实现一个悬浮的桌面侧边工具栏&#xff0c;在工具栏中有画笔绘制&#xff0c;批注的功能&#xff0c;能够实现在任何…

【NLP】一种联合关系抽取模型——TPLinker

背景 前文介绍了【NLP】一种基于联合方式的三元组抽取模型——CasRel.这个模型虽然实体和关系同时训练&#xff0c;但本质上来说还是分阶段的预测实体和关系&#xff0c;依然存在暴露偏差问题。下面介绍一个解决暴露偏差的模型&#xff1a;TPLinker&#xff0c;论文地址&#…

【OJ】A+B=X

&#x1f4da;Description: 数列S中有n个整数&#xff0c;判断S中是否存在两个数A、B&#xff0c;使之和等于X。 ⏳Input: 第一行为T&#xff0c;输入包括T组测试数据。 每组数据第一行包括两个数字n和X&#xff0c;第二行有n个整数&#xff0c;表示数列S&#xff0c;(1&l…

Linux-0.11 文件系统inode.c详解

Linux-0.11 文件系统inode.c详解 Linux-0.11中使用的文件系统为minix&#xff0c; inode.c中的函数和该文件系统强关联。 inode节点在文件系统中与文件相关联&#xff0c;一个文件的就由一个inode来管理&#xff0c;这个inode节点将记录文件的权限&#xff0c;大小&#xff0…

SpringCloud之Nacos

Nacos1. Nacos的概念2. Nacos的作用3. Nacos的下载与安装4. Nacos Client 服务端的搭建5. Nacos 的namespace 和 group6. 配置中心7. 注意点1. Nacos的概念 Nocos 是 SpringCloudAlibaba架构中最重要的组件Nacos 是一个更易于帮助构建云原生应用的动态服务发现、配置和服务挂你…

pytorch搭建手写数字识别LeNet-5网络,并用tensorRT部署

pytorch搭建手写数字识别LeNet-5网络&#xff0c;并用tensorRT部署前言1、pytorch 搭建LeNet-5&#xff0c;并转为ONNX格式1.1 LeNet-5网络介绍1.2 ONNX(Open Neural Network Exchange)介绍1.3 pytorch 搭建 LeNet5网络2、将onnx转为tensorRT2.1 tensorRT 介绍2.1 onnx 转为 te…

C++面向对象(下)

文章目录前言1.再谈构造函数1.初始化列表2.explicit关键字2. static成员1.概念3.友元1.概念2.友元函数3.友元类4. 内部类5.匿名对象6.编译器优化7.总结前言 本文是主要是将之前关于C面向对象中的一些没有归纳到的零星知识点进行补充&#xff0c;同时对C中的面向对象简单收个尾…

如何在ONLYOFFICE v7.3中使用VSTACK和HSTACK公式

大家好&#xff0c;今天来给大家讲解一下&#xff0c;怎样在ONLYOFFICE v7.3中使用VSTACK和HSTACK公式&#xff0c; 这两个新公式也是ONLYOFFICE7.3版本更新后新的计算公式&#xff0c;请大家详细阅读本文。 ONLYOFFICE ONLYOFFICE文档是一款免费开源在线办公软件&#xff0c…

实验室装修|SICOLAB实验室装修方案

实验室装修不外乎通风与洁净的设计为重中之重&#xff0c;以下由SICOLAB介绍分享。一、实验室通风系统主要包含送风系统和排风系统两部分。&#xff08;1&#xff09;送风系统的设计需要考虑以下几个方面&#xff1a;1.1空气质量要求&#xff1a;实验室内的空气需要保持一定的洁…

生物素标记试剂1869922-24-6,Alkyne-PEG3-Biotin PC,炔烃PEG3生物素PC

1、试剂基团反应特点&#xff08;Reagent group reaction characteristics&#xff09;&#xff1a;PC alkyne-PEG3-Biotin含一个炔烃和一个 PEG 链接的可光裂解生物素基团。含 3 个单元 PEG 的 ADC linker&#xff0c;生物素本身是个游离的小分子&#xff0c;在生物实验中常常…

【汽车雷达通往自动驾驶的关键技术】

本文编辑&#xff1a;调皮哥的小助理 现代汽车雷达装置比手机还小&#xff0c;能探测前方、后方或侧方的盲点位置是否存在障碍物&#xff0c;但这还不百分之百实现全自动驾驶的。传统的汽车雷达分辨率都不高&#xff0c;只能“看到”一团东西&#xff0c;可以检测到汽车周围存在…

掌握使用yum为CentOS系统安装软件掌握使用apt为Ubuntu安装软件(扩展)

1.掌握使用yum为CentOS系统安装软件2.掌握使用apt为Ubuntu安装软件&#xff08;扩展&#xff09;1、Linux系统的应用商店 操作系统安装软件有许多种方式&#xff0c;一般分为&#xff1a; •下载安装包自行安装•如win系统使用exe文件、msi文件等•如mac系统使用dmg文件、pkg文…