Vue2电商前台项目——完成Detail详情页模块业务

news2025/1/20 3:42:52

Vue2电商前台项目——完成Detail详情页模块业务

Vue基础知识点击此处——Vue.js

文章目录

  • Vue2电商前台项目——完成Detail详情页模块业务
    • 一、项目开发步骤
    • 二、配置路由规则+滚动行为
      • 1、配置路由规则
      • 2、滚动行为
    • 三、请求详情页数据并展示数据
      • 1、写接口
      • 2、写Vuex仓库
      • 3、派发actions
      • 4、组件拿到后台返回的数据并渲染到页面
    • 四、放大镜展示数据
      • 1、Detail父组件把图片数据传给放大镜子组件
      • 2、解决数据未请求到时获取其属性报错的问题
    • 五、放大镜下轮播图展示数据
      • 1、轮播图三大步
      • 2、动态添加active样式
      • 3、放大镜和轮播图实现联动
    • 六、产品属性展示数据
    • 七、放大镜效果实现
    • 八、购买产品个数的加减操作
      • 1、收集数量并控制个数>0
      • 2、校验用户自己输入的值

一、项目开发步骤

这里已经滚瓜烂熟了哈哈哈哈。。。。

1、准备静态页面
2、拆分组件,配置路由信息
3、写接口,使用Vuex存储数据
4、把服务器数据渲染到页面上

请添加图片描述

这里把详情页Detail组件放到路由组件pages里src/pages/Detail/index.vue

二、配置路由规则+滚动行为

点击商品图片 => 路由跳转并传参 => 跳转到Detail挂载完毕派发actions => 向后台发送请求拿到数据 => 把数据给组件 => 数据渲染到页面

1、配置路由规则

经分析发现,在进行路由跳转时,我们要带上商品的id,这样服务器就能根据商品id去找到对应的商品信息在详情页进行展示,所以我们在配置路由规则时应该使用params参数占位符,路由规则配置如下:

{
    path: '/detail/:skuId?',  //商品id的占位符,跳转时我们要带上商品参数
    component: Detail,
    meta: {
        showFooter: true
    }
},

然后使用声明式路由导航在Search页的商品图片处跳转并传参

请添加图片描述

一般来说,如果路由规则比较多,我们会把路由规则另外写一个js文件引入,这样的话路由器这边会比较清晰,方便写其他东西

// src/router/routes.js
// 本文件用于存储路由的配置规则信息
// 引入路由组件
import Home from "@/pages/Home";
import Search from "@/pages/Search";
import Login from "@/pages/Login";
import Register from "@/pages/Register";
import Detail from "@/pages/Detail";

//配置路由
export default [
  {
    path: "/home",
    component: Home,
    meta: { showFooter: true },
  },
  {
    name: "sousuo",
    //使用params传参时,需要占位
    path: "/search/:keyword?",
    component: Search,
    meta: { showFooter: true },
  },
  {
    path: "/login",
    component: Login,
    meta: { showFooter: false },
  },
  {
    path: "/register",
    component: Register,
    meta: { showFooter: false },
  },
  {
    path: "/detail/:skuid",
    component: Detail,
    meta: { showFooter: true },
  },
  //重定向,在项目跑起来的时候,访问"/",立马让他定向到首页
  {
    path: "*",
    redirect: "/home",
  },
];

再在index.js里引入

请添加图片描述

2、滚动行为

在进行路由跳转时可能滚动条不在最上面。切换路由时,想要页面滚动到顶部,我们可以在路由器中添加一个scrollBehavior函数解决这个问题,返回值是期望滚动到的位置,y:0表示跳转后滚动条距离顶部0px。

export default new VueRouter({
    //配置路由规则
    routes,
    //配置滚动行为
    scrollBehavior(to, from, savedPosition) {
        // 始终滚动到顶部
        return { y: 0 }  //期望滚动到的位置,0意思是跳转后滚动条始终在最上方
    },
})

三、请求详情页数据并展示数据

看以下接口文档:

请添加图片描述

1、写接口

先到api里写接口

请添加图片描述

2、写Vuex仓库

写仓库用来actions接收数据并state存储数据,还有getters简化数据。这里是新建了一个小仓库detail,和homesearch平级,别忘了暴露给大仓库。

这里面要注意getters中数据的写法,因为请求数据是一个异步操作,所以一开始数据是空对象,读空对象身上的属性肯定报错,服务器数据回来后,把state中的原数据替换,getters就能读到值,然后重新响应,所以页面不会有问题,但是控制台肯定会先报错的,如果不想看到这个错误,就让getters中的数据在读不到东西的时候先置空

src/store/detail/index.js
//本文件用于存储Detail详情页的数据
import { reqDetailData } from "@/api";

const state = {
  detailData: {},
};
const actions = {
  async getDetailData(context, skuId) {
    let result = await reqDetailData(skuId);
    console.log(result);
    if (result.code == 200) {
      context.commit("GETDETAILDATA", result.data);
    }
  },
};
const mutations = {
  GETDETAILDATA(state, detailData) {
    state.detailData = detailData;
  },
};
//简化数据
const getters = {};
export default {
  state,
  mutations,
  actions,
  getters,
};

3、派发actions

去Detail组件中派发请求并传参过去

请添加图片描述

注意:这里的skuid是大写小写,最好去开发者工具看看。

这里由于我们在进行从Search到Detail路由跳转的时候把当前商品的id传参传过去了,传给了$route,所以我们可以通过this.$route.params.skuId拿到商品id并把它派发给actions发送ajax请求。(之所以是params.skuId是因为占位符写的skuId)

请添加图片描述

4、组件拿到后台返回的数据并渲染到页面

我们需要的数据都在state.detailData.XXX里,如果每个都直接这样写的话很麻烦,我们可以用getters简化一下。

src/store/detail/index.js
//简化数据
const getters = {
  categoryView(state) {
    //因为返回的时候可能异步操作还没把数据请求过来,所以要加个或空
    //服务器数据回来后,把state中的原数据替换,getters就能读到值,然后重新响应
    return state.detailData.categoryView || {};
  },
  skuInfo(state) {
    return state.detailData.skuInfo || {};
  },
  spuSaleAttrList(state) {
    return state.detailData.spuSaleAttrList || [];
  },
};

仓库根据参数拿到后台数据后,Detail通过mapGetters来获取数据,然后根据数据的结构把它们展示到页面的对应位置,展示数据比较简单。

先用计算属性捞一下getters:

computed: {
    ...mapGetters('detail', ['categoryView', 'skuInfo', 'spuSaleAttrList'])
  }

找到对应位置的对应数据:

请添加图片描述

在对应位置展示:

请添加图片描述

四、放大镜展示数据

1、Detail父组件把图片数据传给放大镜子组件

观察数据,发现放大镜这部分的图片数据存储在skuInfo里的一个数组中

请添加图片描述

使用props让父组件Detail给子组件传值,下图左边是父组件右边是子组件

请添加图片描述

然后把数组中第一张图片拿过来展示作为默认显示,但是这样会有bug,如下

2、解决数据未请求到时获取其属性报错的问题

问题的关键:不能出现undefined.xxx

请求数据是异步操作,所以getters中的数据skuInfo没有读到的话,会先返回空对象,然后去读取空对象身上的属性,肯定会报错,但是后边数据请求回来了,又会重新渲染重新响应,所以页面显示正常,但是控制台会先报一个错,解决办法还是加个逻辑或把它置空一下子 || []

请添加图片描述

其实这个bug的关键就是,不能出现undefined.xxx。前三步都好理解,关键是第四步这个地方,其实空数组[0]肯定是undefined,然后undefined.imgUrl肯定是会报错的,这种情况的话可以弄一个计算属性,如果传过来的是空数组,那么skuImageList[0]就先或一个空对象(因为数组内的元素都是对象),空对象.imgUrl是undefined,这样页面没请求到数据的时候就不会报错了

请添加图片描述

五、放大镜下轮播图展示数据

这个轮播图和我们之前封装的那个全局轮播图组件样式是不一样的,所以全局组件不能拿过来用,我们这里需要自己再重新定义一下

1、轮播图三大步

还记得做轮播图的三大步吗?还是那几个:引包=>搭建页面=>添加js

其中第三步还是采用watch+$nextTick,等数据请求过来且v-for遍历生成完毕后生成swiper实例。

有点忘记的可以参考一下我前面的笔记,原生js写的和引包的都有写——引包写法、原生JS写法。

  watch: {
    //监听skuImageList数据的变化
    // 因为它会有一个从空数组变成有数据的过程(一切都因为请求数据是一个异步操作)
    skuImageList(newVal, oldVal) {
      //nextTick能保证页面结构先渲染出来,然后再执行回调函数
      this.$nextTick(function () {
        new Swiper(".swiper-container", {
          //前进后退按钮
          navigation: {
            nextEl: ".swiper-button-next",
            prevEl: ".swiper-button-prev",
          },
          slidesPerView: 4, // 显示几个图片设置
          slidesPerGroup: 1, // 每一次切换图片的个数
        });
      })
    }
  },

2、动态添加active样式

鼠标点击某小图时动态添加active样式,这里简单的话可以直接搞个hover样式,但是为了练习js,还是搞点复杂的吧。

请添加图片描述

src/pages/detail/ImageList

<div class="swiper-slide" v-for="(slide,index) in skuImageList" :key="slide.id">
   <img :src="slide.imgUrl" :class="{active:currentIndex==index}" @click="changeCurrentIndex(index)"/>
</div>

....
<script>
...
  data(){
    return {
      // 响应式数据
      currentIndex: 0,  //0表示默认是第一张图
    }
  },
  methods:{
    // 修改响应式数据
    changeCurrentIndex(index){
      this.currentIndex = index;
    }
  },
</script>

3、放大镜和轮播图实现联动

点击轮播图(ImageList组件)的图片,就把当前图片的索引传给放大镜(Zoom组件),那么这里就涉及到了兄弟组件通信,可以直接使用全局总线通信。

1、首先给放大镜这边绑定全局事件
2、去轮播图这边触发事件并把当前图片对象的索引值传过去
3、触发事件后执行回调,把当前索引值通过data给计算属性中的imgObj
4、vue检测到data的改变,重新解析模板,更新页面
5、注:默认放大镜data中的index是0,这样默认就会显示第一张图片。默认轮播图data中currentIndex是0,这样默认轮播图第一张图片有active样式。

请添加图片描述

六、产品属性展示数据

请添加图片描述

我们前面在getters已经获取并简化了数据:

请添加图片描述

mapgetters引入一下:

请添加图片描述

在对应位置进行展示:

请添加图片描述

这里我们要实现点击某个属性时该属性高亮,其他属性变灰的效果,用到排他思想

首先应该给每个属性绑定点击事件,并且传入两个参数

请添加图片描述

第一个参数是当前售卖属性值所在的那个对象spuVal,第二个参数是所有售卖属性对象所在的数组spu.spuSaleAttrValueList

然后这里由于active样式我们是动态添加的,它是否展示取决于spuVal对象的isChecked属性是1还是0,这里都是我们从服务器拿过来的属性且配置到了计算属性里,所以一旦它们里面的数据改变,vue就会重新解析模板,这样的话我们就可以通过修改isChecked属性来控制active样式是否显示,所以回调可以这么写:

methods: {
    //产品售卖属性切换,排他思想
    changeActive(spuVal, spuValArr) {
      //第一个参数是当前售卖属性值所在的对象,第二个参数是所有售卖属性对象所在的数组
      spuValArr.forEach(el => {
        el.isChecked = '0';  //先把数组中每个对象的active样式去掉
        spuVal.isChecked = '1';  //再给当前点击的对象添加active样式
      });
    }
  }

七、放大镜效果实现

pageX: 页面X坐标位置
pageY: 页面Y坐标位置

offsetX:鼠标坐标到元素的左侧的距离
offsetY:鼠标坐标到元素的顶部的距离

offsetLeft: 该元素外边框距离包含元素内边框左侧的距离
offsetTop:该元素外边框距离包含元素内边框顶部的距离
offsetWidth: width + padding-left + padding-right + border-left + border-right
offsetHeight: height + padding-top + padding-bottom + border-top + border-bottom

这些元素偏移量如果不太熟悉的话可以点此复习一下——PC端网页特效

在放鼠标移动事件的这个div里绑定鼠标移动事件

请添加图片描述

请添加图片描述

看注释,反正就是计算一下,记得修改style要加px
这里还要注意右边的放大图这里,图片的top和left要多一倍(因为放大图是放大一倍),而且要和这块儿绿东西的top和left反的着来(移动图片,多余的部分是overflow:hidden的)。绿框往右下角动,图片往左上角动才对

handlerMask(e) {
 	//1.获取这个遮罩层的dom元素
	let mask = this.$refs.mask;
	 //2.计算定位的left和top
	 let x = e.offsetX - mask.offsetWidth / 2;
	 let y = e.offsetY - mask.offsetWidth / 2;
	 //3.约束条件防止盒子跑出去
	 if (x < 0) x = 0; //防止从左边跑出去
	 if (x > mask.offsetWidth) x = mask.offsetWidth; //防止从右边跑出去
	 if (y < 0) y = 0; //防止从上边跑出去
	 if (y > mask.offsetWidth) y = mask.offsetWidth; //防止从下边跑出去
	 //4.修改dom样式
	 mask.style.left = x + 'px';
	 mask.style.top = y + 'px';
	
	 //右边的放大图跟着变化
	 let big = this.$refs.big;
	 big.style.top = - 2 * y + 'px';
	 big.style.left = - 2 * x + 'px';
}

八、购买产品个数的加减操作

这个数量的框既可以点击加减按钮操作,也可以用户自己输入

1、收集数量并控制个数>0

请添加图片描述

这块的话我们肯定是要收集这个商品的数量然后后边要显示计算价格啥的,所以这里的话可以使用v-model收集一下子,然后点击加号就+1,点击减号就-1,但是这个数量不能<1,所以减号这里要加个判断。

请添加图片描述

2、校验用户自己输入的值

用户可能输入任何花里胡哨的值,所以我们要对其进行校验,首先给这个输入框绑定一个onchange事件,当加入购物车数量输入框的内容改变时离开焦点触发此函数

请添加图片描述

这里对三种情况进行校验

第一种:用户输入非数值字符串 ,让它乘以1,因为任何非数值字符串乘以1都会是NaN
第二种:用户输入负数,这种情况和第一种情况如果有一个出现,那么就置为默认值1
第三种:用户输入小数,直接改为取整

changeSkuNum(event) {
      // 拿到用户输入的值做校验
      let value = event.target.value * 1; //1.任何非数值字符串乘以1都会是NaN
      if (isNaN(value) || value < 1) {
        this.skuNum = 1; //2.如果用户输入非数值字符串或负数,那么就改成1
      }
      //3.如果用户输入正常,就向下取整(避免用户输入小数点)
      else {
        this.shopCarNum = parseInt(value);
      }
    },

详情页的笔记差不多整理到这啦,下一篇整理购物车模块相关的的笔记。

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

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

相关文章

ESP32S3的ESP_LOGx()控制台输出详细介绍

前言 &#xff08;1&#xff09;接触一款新的芯片&#xff0c;第一步要么是点灯&#xff0c;要么是进行串口的输出。现在我将介绍如何快速的利用ESP32S3进行控制台的日志输出。 &#xff08;2&#xff09;对于ESP32进行日志输出还是相对简单的&#xff0c;不像其他芯片需要配置…

三维模型3DTile格式轻量化压缩的遇到常见问题与处理方法分析

三维模型3DTile格式轻量化压缩的遇到常见问题与处理方法分析 三维模型的轻量化压缩是一项技术挑战&#xff0c;特别是在处理复杂的3DTile格式时。下面列举了一些处理过程中可能遇到的常见问题以及相应的处理方法&#xff1a; 模型精度损失&#xff1a;在进行压缩处理时&#x…

C语言入门Day_19 初识函数

目录 1.函数的定义 2.函数的调用 3.易错点 4.思维导图 前言&#xff1a; printf()我们已经很熟悉了&#xff0c;它有一个特定的功能&#xff0c;就是在屏幕上输出一行文字。之前的课程我们都称呼printf()为一个功能&#xff0c;实际上ta在编程中有个特定的名字——函数。 …

IO和进程day07(IPC、管道、信号)

今日任务 1.代码&#xff08;一次只能发一次消息&#xff0c;不然会存在一些小问题&#xff0c;在接受消息之后会立刻输出上次的第二次发送的消息&#xff09; read.c文件&#xff08;先读取消息&#xff09; #include <stdio.h> #include <string.h> #include &…

org.apache.ibatis.binding.BindingException: Invalid bound statement

在学习黑马头条遇到的关于使用mapper执行方法出现的错误 完整报错信息为&#xff1a;org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.heima.wemedia.mapper.WmNewsMaterialMapper.saveRelations 译为&#xff1a;无效的绑定语句&…

Ubuntu 23.10/24.04 LTS 放弃默认使用 snap 版 CUPS 打印堆栈

导读Canonical 的开发者、OpenPrinting 的项目负责人 Till Kamppeter 今年 5 月表示&#xff0c;计划在 Ubuntu 23.10&#xff08;Mantic Minotaur&#xff09;上默认使用 Snap 版本的 CUPS 打印堆栈。 不过经过数月的测试&#xff0c;官方放弃了这项决定。Ubuntu 23.10&#x…

MySQL面试题——隔离级别相关面试题

隔离级别相关面试题 MySQL事务隔离级别 未提交读——可以读到其他事务未提交的数据&#xff08;最新的版本&#xff09; 错误现象&#xff1a;脏读、不可重复读、幻读的现象 提交读&#xff08;RC&#xff09;——可以读到其他事务已提交的数据&#xff08;最新已提交的版本&…

TypeScript命名空间和模块

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 命名空间&#xff08;Namespace&#xff09; 命名空间&#xff08;Namespace&#xff09;使用场景 第三方库 兼容…

蓝桥杯官网填空题(迷宫)

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 X 星球的一处迷宫游乐场建在某个小山坡上。它是由 1010 相互连通的小房间组成的。 房间的地板上写着一个很大的字母。我们假设玩家是面朝上坡的方向站立&#xff0…

Spring 的创建和日志框架的整合

目录 一、第一个 Spring 项目 1、配置环境 2、Spring 的 jar 包 Maven 项目导入 jar 包和设置国内源的方法&#xff1a; 3、Spring 的配置文件 4、Spring 的核心 API ApplicationContext 4、程序开发 5、细节分析 &#xff08;1&#xff09;名词解释 &#xff08;2&…

LeetCode 362 期周赛

8029.与车相交的点 题目&#xff1a; 给你一个下标从 0 开始的二维整数数组 nums 表示汽车停放在数轴上的坐标。对于任意下标 i&#xff0c;nums[i] [starti, endi] &#xff0c;其中 starti 是第 i 辆车的起点&#xff0c;endi 是第 i 辆车的终点。 返回数轴上被车 任意部…

自动化控制系统的设计重点是什么?

要实现对选择性激光烧结系统预热温度的控制&#xff0c;需要找到合理的控制对象模型&#xff0c;但选择性激光烧结设备的预热温度场是一个复杂的非线性系统&#xff0c;很难找到合理的控制对象模型来实现预热温度场的温度控制。模糊控制不需要具体的控制模型&#xff0c;预热温…

Linux命令200例:dnsconf用于配置和管理域名解析服务

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;CSDN领军人物&#xff0c;全栈领域优质创作者✌。CSDN专家博主&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0…

极限的概念与性质

目录 极限的概念 极限的性质 极限的存在准则 极限的概念 极限是数学中的分支——微积分的基础概念&#xff0c;它表示无限趋近于一个固定的数值的过程。在高等数学中&#xff0c;极限可以分为数列极限和函数极限。 1.数列的极限 数列的极限是指对于一个数列{an}中的任意一…

socket编程|TCP

一.套接字概念 套接字&#xff08;Socket&#xff09;是一种用于网络通信的编程接口&#xff0c;它提供了一种机制&#xff0c;使得不同计算机上的应用程序能够通过网络进行通信和交换数据。 套接字可以看作是应用程序和网络之间的端点&#xff0c;它定义了应用程序与网络之间…

400电话:提供全方位客户服务的热线电话

随着现代社会的发展&#xff0c;企业和机构越来越重视客户服务的质量和效率。为了更好地满足客户的需求&#xff0c;提供及时的帮助和解决方案&#xff0c;许多企业纷纷引入了400电话这一全方位客户服务的热线电话。 400电话是一种以4开头的电话号码&#xff0c;通过该号码可以…

[论文阅读]Coordinate Attention for Efficient Mobile Network Design

摘要 最近关于移动网络设计的研究已经证明了通道注意力(例如&#xff0c; the Squeeze-and-Excitation attention)对于提高模型的性能有显著的效果&#xff0c;但它们通常忽略了位置信息&#xff0c;而位置信息对于生成空间选择性注意图非常重要。在本文中&#xff0c;我们提出…

Redis 三种特殊的数据类型 - Geospatial地理位置 - Hyperloglog基数统计的算法 - Bitmaps位图(位存储)

目录 Redis 三种特殊的数据类型&#xff1a; Geospatial&#xff1a;地理位置 Geospatial类型常用的命令&#xff1a; GEOADD&#xff1a;添加地理位置 GEOPOS&#xff1a;获取地理位置 GEODIST&#xff1a;返回两个给定位置之间的距离 GEORADIUS&#xff1a;以给定的经纬…

公司电脑文件加密防泄密软件系统——「天锐绿盾」

天锐绿盾是一款功能强大的公司电脑文件加密防泄密软件系统&#xff0c;旨在保护企业的知识产权和商业机密。 PC访问地址&#xff1a;http://985.so/2y2n9 它具有以下几个主要特点&#xff1a; 文件加密&#xff1a;天锐绿盾会对存储在公司电脑上的所有敏感文件进行自动加密&am…

uniapp——实现电子签名功能——基础积累

话说&#xff0c;2020年刚来杭州的时候&#xff0c;有用到过uniapp&#xff0c;距今已有三年时间了&#xff0c;果然全忘了&#xff0c;哈哈[笑中带泪] 昨天遇到一个需求&#xff1a;就是要实现pdf文件的预览&#xff0c;着实费了我很多的时间&#xff0c;连晚饭都没有吃好。。…