Vue2电商项目(四) Detail模块

文章目录

  • 一、配置Detail路由
    • 1. 将Detail组件配置为路由组件
    • 2. 将路由配置文件拆分
    • 3. 声明式导航跳转到Detail
      • 跳转时存在的问题:页面滚动条还在下边
  • 二、配置API及vuex
  • 三、放大镜及下方轮播图
    • 1. Detail组件传递放大镜数据
    • 2. 读取vuex数据的经典错误undefined
    • 3. 放大镜放大效果
    • 3. 放大镜下方的轮播图
      • 数据
      • 轮播图
      • 点击高亮
    • 4. 放大镜与轮播图联动
  • 四、 选择售卖属性
    • 1. 渲染页面
    • 2. 排他思想
  • 五、购买产品个数的加减操作

一、配置Detail路由

1. 将Detail组件配置为路由组件

在这里插入图片描述
当点击某个商品调转到详情页时,需要将这个商品的id传递过去。所以这里配置了params占位。

2. 将路由配置文件拆分

就是将路由配置项里的内容提取到另一个文件中,这样更清晰。
在这里插入图片描述

3. 声明式导航跳转到Detail

Search组件中,将原来的a标签替换为router-link,记得携带params参数,将商品Id传过去。
在这里插入图片描述


在跳转路径上可以检查传递的参数是否正确:
在这里插入图片描述

跳转时存在的问题:页面滚动条还在下边

正常情况,跳转到新页面时,应该处于新页面的最前面。
从图中可以看出,页面跳转前滚动条处于底部。页面跳转后滚动条还是处于底部。所以这是个问题:
在这里插入图片描述

解决方法:查看官网:滚动行为
在这里插入图片描述
在路由配置里添加一个新的配置项:

// router/index.js
export default new VueRouter({routes,scrollBehavior (to, from, savedPosition) {// return 期望滚动到哪个的位置return { y: 0 }}
})

二、配置API及vuex

根据接口文档,写获取商品详情的api

//api/index.js
// 获取商品详情 url:/api/item/{商品id} 请求方式 get
export const reqGoodsInfo = (goodsId) => {return requests({ url: `/item/${goodsId}`, method: 'get' })
}

获取来的数据依然是存在仓库里,detail又是一个模块。建立detail小仓库存储这个模块的信息

// store/detail/index.js
import { reqGoodsInfo } from "@/api";export default {namespaced: true,state: {goodsInfo: {}},actions: {async getGoodsInfo (context, goodsId) {const result = await reqGoodsInfo(goodsId)if (result.code === 200) {context.commit('GETGOODSINFO', result.data)}}},mutations: {GETGOODSINFO (state, goodsInfo) {state.goodsInfo = goodsInfo}},getters: {  }
}

不要忘记把这个小仓库放在大仓库里
在这里插入图片描述

三、放大镜及下方轮播图

1. Detail组件传递放大镜数据

在vuex中,通过getters简化获取到goodsList里的skuInfo。Detail组件获取到后,将该信息传递给子组件Zoom

// store/detail/index.js
getters: {skuInfo (state) {return state.goodsInfo.skuInfo}}

左边Detail父组件,右边Zoom子组件.(这里先写死数据,后续再改)
在这里插入图片描述

2. 读取vuex数据的经典错误undefined

在这里插入图片描述
问题:根据提示可知是Zoom组件里的skuImageList[0]有问题。skuImageList是父组件传递的。经过mounted函数测试发现,父组件传递过来的是undefined

因为请求数据是异步操作,如果还没有数据,getters中的数据skuInfo返回的是空对象。去读空对象身上的属性,则会报错为undefined。所以skuInfo.skuImageList是undefined。

解决

<!--如果不存在这个数据,就给子组件Zoom传递一个空数组--><Zoom :skuImageList="skuInfo.skuImageList || []" />

然后又报错
在这里插入图片描述

在Zoom组件中读取了skuImageList[0].imageUrlskuImageList是空数组,那么skuImageList[0]就已经是undefined了 ,所以读取imageUrl也会报错了。

在这里插入图片描述
解决
思路同上,这里给一个空对象

// Zoom组件computed: {imgObj () {return this.skuImageList[0] || {}}}

在这里插入图片描述

3. 放大镜放大效果

offsetX:鼠标坐标到元素的左侧的距离
offsetY:鼠标坐标到元素的顶部的距离
offsetLeft: 元素与定位父级元素的左侧的距离
offsetTop:元素与定位父级元素的顶侧的距离
offsetWidth: 元素自身宽度(width + padding+border)
offsetHeight: 元素自身高度 (height + padding+border)

回顾博客:WebAPI(二) offset
在这里插入图片描述

这里主要包含两个步骤:
(1)、鼠标移动,mask跟着移动
(2)、右侧的放大效果实时变化

首先给mask加一个鼠标移动事件,为了后续方便对节点操作,同时加上ref属性。(为什么给event加鼠标移动事件?)
在这里插入图片描述
具体业务逻辑看代码吧,结合注释计算一下,注意不要忘了修改属性的时候加单位px
处理第二个步骤时,需要注意,鼠标的移动与右侧大图呈现的方向是相反的。所以要加负号(加负号注意)。

<script>handlerMask (event) {// 1. 获取mask节点let mask = this.$refs.mask// 2. 修改位置,不要忘了加单位!(可以用鼠标的位置是因为鼠标总位于mask    的中心)let x = event.offsetX - mask.offsetWidth / 2  // x水平方向,确定位置,看左侧let y = event.offsetY - mask.offsetHeight / 2 // y垂直方向,确定位置,看上边// 3. 加限制if (x < 0) x = 0 // 小于0,mask就从左边出去了if (x > mask.offsetWidth) x = mask.offsetWidth // mask的宽是父级元素的一半,如果x坐标超过了这一半,说明右边出去了if (y < 0) y = 0 // 小于0,mask就从下边出去了if (y > mask.offsetHeight) y = mask.offsetHeight // mask的高是父级元素的一半,如果y坐标超过了这一半,说明上边出去了// 4. 修改绿色mask的位置 mask.style.left = x + 'px'mask.style.top = y + 'px'// 放大图的地方let big = this.$refs.bigbig.style.top = -2 * y + 'px'big.style.left = -2 * x + 'px'}</script>

3. 放大镜下方的轮播图

回顾之前做过的轮播图(和之前的有点不一样(同时展示三张图片),所以这里不用当初定义的全局组件了):Vue2电商项目(二)、Home模块轮播图

在这里插入图片描述

数据

由于这里用到的数据和Zoom(放大镜)一样,所以同样由Detail组件传递给ImageList组件。

 <!-- Detail组件,小图列表 --><ImageList :skuImageList="skuInfo.skuImageList || []" />

轮播图

引包、引样式、创建实例。创建实例仍然在watch中。
在这里插入图片描述
注意v-for应该加在哪,ref应该加在哪!!!

  watch: {// 监听数据:可以保证数据一定ok,但是不能保证v-for遍历结构是否完事儿//监听skuImageList数据的变化,会有一个从空数组变成有数据的过程(一切都因为请求数据是一个异步操作)skuImageList () {this.$nextTick(() => {new Swiper(this.$refs.mySwiper, {// 如果需要前进后退按钮navigation: {nextEl: '.swiper-button-next',prevEl: '.swiper-button-prev',},slidesPerView: 3, // 设置能够同时显示的slides数量slidesPerGroup: 1, // 每一次切换图片的个数})})}}

点击高亮

不用css,改用js实现点击高亮效果。这个和TypeNav组件里的情况一致。
高亮时,添加active这个class类。
在这里插入图片描述

  <divclass="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>

4. 放大镜与轮播图联动

点击轮播图里的某张图,放大镜的主图里就展示某张图。很明显,这两个组件是兄弟组件,所以涉及到组件间通信。采用全局事件总线的方式。

传递数据:ImageList组件,传递的是被点击的图片对象的id。
接收数据:Zoom组件。

在这里插入图片描述
ImageList组件中用到了之前高亮写的函数。当点击图片时,显示高亮,并通过事件总线 将该图片的索引值传递过去。
在这里插入图片描述

四、 选择售卖属性

在这里插入图片描述

1. 渲染页面

在这里插入图片描述

// vuex小仓库里
getters: {spuSaleAttrList (state) {return state.goodsInfo.spuSaleAttrList || []}
}

在这里插入图片描述

2. 排他思想

需求:点击某一个属性时,该属性高亮,其他属性都是灰的。
在这里插入图片描述

排他思想:(有同一组元素,想要某一个元素实现某种样式,需要用到循环的排他思想)
(1) 所有的元素全部清除样式(干掉其他人)
(2) 给当前元素设置样式(留下自己)
(3) 注意顺序不能颠倒,首先干掉其他人,再设置自己。
参考博客:JS排他思想

添加点击事件:
在这里插入图片描述
数据结构:

[
// 第一个属性{id:1saleAttrName:'颜色'// 属性值对象数组spuSaleAttrValueList:[{id:1,valueName:'亮黑色',isChecked:'0'},{id:2,valueName:'粉色',isChecked:'1'},{id:3,valueName:'白色',isChecked:'1'},]},//第二个属性
...
]

思路分析: 首先要获取到当前选中的元素对象(比如值为白色的对象),给该对象的isChecked赋值,使其高亮。其次还要获取到这个元素对象所在的数组(即spuSaleAttrValueList),对该数据里的其他对象进行遍历,将isChecked赋值,使其不高亮。

methods: {// 售卖属性的排他操作// 第一个参数是选中的对象,第二个是这个对象所在的数组changeActive (currentValue, spuValueList) {spuValueList.forEach(el => {// 先都赋值为0,不高亮el.isChecked = '0'});// 选中的赋值为1,高亮currentValue.isChecked = '1'}
}

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

需求:点击+:数字加1;点击-:数字减1;输入框里可输入产品数量。
在这里插入图片描述
data里定义商品数量属性skuNum,默认值是1;+和- 需要注意的就是减的时候商品数量不能小于1。
在这里插入图片描述
输入框的回调函数里需要处理用户一些非法的输入。非法输入有这样几种情况:输入文本,负数,小数;

 // 改变商品个数changeSkuNum (e) {// 文本*1 是NaNlet value = e.target.value * 1// 非法情况: 出现NaN或者小于1if (isNaN(value) || value < 1) {this.skuNum = 1} else {// 正常大于1 【不能出现小数】this.skuNum = parseInt(value)}}

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

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

相关文章

力扣234 回文链表 Java版本

文章目录 题目描述代码 题目描述 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为 回文链表 。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,2,1] 输出&#xff1a;true 示例 2&…

【集合拆分+多线程并行处理,拿来即用】

文章目录 一.业务场景二.拆分流程三. 简单上个List拆分的demo四.测试结果五.小结 一.业务场景 节假日后第一天&#xff0c;上完班有点累&#xff0c;回到家稍微写点简单的东西。 我们项目里面有这样一业务场景&#xff0c;要计算全公司所有人某几个月内每天的考勤机打卡加班工时…

docker从0到1运行mysql(最详细且绝对成功版)

前置环境 CentOS7.8 安装docker yum install -y docker 启动docker并检查docker状态 systemctl start docker systemctl status docker 这样即正常 设置镜像加速 修改 /etc/docker/daemon.json 文件并添加上 registry-mirrors 键值 vim /etc/docker/daemon.json …

set的使用

序列式容器和关联式容器 序列式容器&#xff1a; 前⾯我们已经接触过STL中的部分容器如&#xff1a;string、vector、list、deque、array、forward_list等&#xff0c;这些容器统称为序列式容器&#xff0c;因为逻辑结构为线性序列的数据结构&#xff0c;两个位置存储的值之间…

监控和维护 Linux 系统的健康状态:从服务启动故障到操作系统查询

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

启动 Ntopng 服务前需先启动 redis 服务及 Ntopng 常用参数介绍

启动Ntopng服务之前需要先启动redis服务&#xff0c;因为Ntopng服务依赖于redis服务的键值存储。 服务重启 服务启动 Ntopng常用参数&#xff1a; -d 将 Ntopng 进程放入后台执行。默认情况下&#xff0c;Ntop 在前台运行。 -u 指定启动Ntopng执行的用户&#xff0c;默认为…

C++ SLT标准模板简介

STL全称是standard template libaray 标准模板库&#xff0c;这个库是C库中十分重要的一部分&#xff0c;里面涵盖可复用的组件库&#xff0c;而且是一个包罗了数据结构与算法的软件框架。 STL各主要版本 stl库最初是由Alexander Stepanov、Meng Lee在惠普工作室中完成的原始…

Multisim简体中文版百度云下载(含安装步骤)

如大家所熟悉的&#xff0c;Multisim是一款基于电路仿真的软件&#xff0c;可用于电子工程师、电子爱好者和学生进行电路设计、分析和调试。Multisim具有完整的电路设计和仿真功能&#xff0c;可支持模拟电路、数字电路&#xff0c;以及混合电路。 Multisim可以模拟不同电路的…

基于vue框架的大参林药品信息管理系统的设计与实现8b4gt(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;用户,药品分类,药品信息,医生 开题报告内容 基于Vue框架的大参林药品信息管理系统的设计与实现开题报告 一、引言 随着医疗健康行业的快速发展和信息化浪潮的推进&#xff0c;药品信息管理已成为提升医疗服务效率、保障患者用药安全、…

怎样摆脱繁重的“物理集中”,轻松连接与交付全域数据,真正实现“敏捷用数”?

Data Fabric&#xff08;数据编织&#xff09;&#xff0c;作为新一代的数据管理策略&#xff0c;其核心在于通过逻辑层面的数据整合与加工&#xff0c;打破物理集中的局限&#xff0c;实现数据的无缝共享与高效利用。以往&#xff0c;我们更多地从理论层面探讨数据编织的技术与…

RK3229 MS8416 MS8406调试

1、I2S做从机模式&#xff0c;音频芯片做主模式 由于音频芯片做从模式声音可能会失真&#xff0c;所以必须使得I2S1做从模式&#xff0c;音频芯片做主模式 ms84x6 {compatible "rockchip,ms84x6";pinctrl-0 <&lk_ms84x6_io>;//ms84x6_sda <&gpi…

目标检测系列(三)yolov2的全面讲解

YOLOv2&#xff08;论文原名《YOLO9000: Better, Faster, Stronger》&#xff09;作为该系列的第二个版本&#xff0c;对原始YOLO进行了显著的改进&#xff0c;进一步提高了检测速度和准确度。在精度上利用一些列训练技巧&#xff0c;在速度上应用了新的网络模型DarkNet19&…

小阿轩yx-Ansible部署与应用基础

小阿轩yx-Ansible部署与应用基础 前言 由于互联网的快速发展导致产品更新换代速度逐步增长&#xff0c;运维人员每天都要进行大量的维护操作&#xff0c;按照传统方式进行维护使得工作效率低下。这时部署自动化运维就可以尽可能安全、高效的完成这些工作。 Ansible 概述 什…

自闭症寄宿学校陕西:提供综合发展的教育环境

星贝育园&#xff1a;自闭症儿童的综合发展摇篮 在自闭症儿童教育的广阔领域里&#xff0c;寄宿制学校以其独特的康复环境和全方位的支持体系&#xff0c;为这些特殊的孩子点亮了希望之灯。广州的星贝育园自闭症儿童寄宿制学校&#xff0c;正是这样一所充满爱心与专业的机构&a…

探索自闭症寄宿学校:为孩子的未来铺设坚实基石

探索自闭症寄宿学校&#xff1a;星贝育园——为孩子的未来铺设坚实基石 在自闭症儿童成长的道路上&#xff0c;选择一所合适的学校&#xff0c;无疑是为他们铺设坚实基石的关键一步。广州的星贝育园自闭症儿童寄宿制学校&#xff0c;以其专业的教育理念、全面的支持体系和温馨…

使用PLSQL Developer快速连接数据库

文章目录 前言一、定义设置方式二、固定用户设置方式三、连接设置方式总结前言 PLSQL Developer是一个集成开发环境,由Allround Automations公司开发,专门面向Oracle数据库存储的程序单元的开发。该工具提供了多种设置方式,便于使用者在不需要输入用户名称、密码的情况下,…

鸿蒙 如何退出 APP

terminateSelf() 停止Ability自身 在EntryAbility中这么使用 this.context.terminateSelf()在Pages页面中这么使用 import { common } from kit.AbilityKit (getContext(this) as common.UIAbilityContext)?.terminateSelf() 也可以直接封装&#xff1a; import common f…

查了好几天的问题终于画上了句号

问题背景&#xff1a; 产品接到前方实施反馈9月02日有些订单查不到签名值&#xff0c;对于医院验签查不到签名值&#xff0c;就无法完成验签数据归档。 问题追踪过程&#xff1a; 1 首先查数据库&#xff0c;发现订单id确实查不到对应的detail数据&#xff1b; 第一直觉是否是…

如何使用ssm实现基于Java web的高校学生课堂考勤系统的设计与实现+vue

TOC ssm686基于Java web的高校学生课堂考勤系统的设计与实现vue 第一章 课题背景及研究内容 1.1 课题背景 信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突如其来的互联网让传统的信息管理看到了革命性的曙光&#xff0c;因为传统信息管理从时效性&#x…

SpringBoot集成微信小程序Demo

一、前言 小程序是一种全新的连接用户与服务的方式&#xff0c;它可以在微信内被便捷地获取和传播&#xff0c;同时具有出色的使用体验。 微信小程序官方文档&#xff1a;https://developers.weixin.qq.com/miniprogram/dev/framework/ 二、技术栈 SpringBoot 2.0MyBatis-P…