Vue项目开发二-详情页
-
详情页跳转
项目需求:点击首页商品,跳转到商品的详情页
项目实现
—通过路由跳转实现详情页的切换,另外点击事件需要绑定在商品列表项目GoodsItemList组件上;
—因此需要在路由映射文件下创建详情页的映射,并且这里需要注意我们使用的是动态跳转路由,因为需要携带id信息,方便请求不同详情页的数据信息;
—这里通过
push
完成路由跳转,因为需要通过back
返回首页; -
详情页导航栏
项目需求:详情页导航栏,包括商品的相关参数和一个返回首页的图标;
项目实现
—复用之前我们封装的顶部导航组件,这里可在
data()
中传入导航内容;—分别为导航内容和返回首页图标添加点击监听事件,实现点击样式的改变和路由跳转
this.router.back()
返回首页的效果; -
详情页轮播图
项目需求:详情页中实现轮播图效果
项目实现
—设计网络请求函数,从服务器请求详情页相关数据信息,这里需要注意要运用动态跳转路由,不同详情页携带不同id,请求到的数据也有所不同;因此路由映射中设置动态路由:
path:'/detail/:id'
;根据跳转路由的id
信息请求不同详情页的数据;—详情页数据解构分析,我们一般请求到数据结构十分复杂,需要对请求到的数据进行结构分析,拿到我们所需要的数据信息;
—这里轮播图复用轮播图组件,并通过
props
拿到详情页组件请求到的数据;—这里需要注意,之前包裹动态组件,在进行组件切换过程中将状态缓存,更好的实现DOM渲染;在详情页中,我们点击商品需要跳转到不同的详情页,所以需要通过
exclude
属性指定详情页不进行状态缓存,每次都需要重新创建组件;如果缓存或者不缓存没有生效,需要在路由映射中添加name
属性,可能还需要添加meta
属性:meta:{keepAlive:false/true}
表示不被缓存/缓存; -
商品基本信息和商家店铺信息展示
项目需求:商品的详细信息和相关价格描述,商家店铺信息的展示
项目实现
这两个组件的实现重点在于:数据提取整合!!
—这里网络请求的数据需要进行提取处理,不同信息整合为一个对象,传递给我们封装的商品展示组件,这样方便组件开发的过程中只面向一个对象实现数据信息的展示;面向类开发:这里我们把多个数据封装到类里面,这样可以实现一个类封装多组数据,创建类对象,让组件面向类对象实现数据处理!!
—
v-for
语法:可以使用数字进行遍历,例如:v-for = "n in 10"
这样会产生1-10的数字;—如何判断对象是空对象,可以使用
Object.keys
判断是否存在键:Objec.keys(onj).length === 0
-
详情页商品页详细展示
项目需求:详情页下拉商品的详细展示
项目实现
—请求数据进行组件封装即可,这里涉及的重点是图片加载完毕后,滚动长度的计算,在之前轮播图中设计的图片加载完毕实现滚动条长度计算,只需要监听轮播图中一张图片的加载,这里我们需要将所有的图片加载都进行监听,因为它是竖向展示!
—为了减少回调函数向父组件的传递,需要进行一次判断,判断所有图片都加载完毕后,传递回调,设置计数器,计数图片加载次数,当加载次数等于图片长度,说明加载完毕,这样传递回调即可:
if(++this.counter === this.imagesLength)
—图片长度的获取:因此数据默认传递的是空值,获取的数值是0,我们可以通过
watch
进行监听数据变化,当网络请求数据后(create生命周期中数据请求完成后),再获取请求完毕后最新的图片列表的大小;watch:{detailInfo(){this.imagesLength = this.detailInfo.detailImage[0].list.lenght}}
-
详情页评论信息展示
项目需求:实现用户评论信息的展示
项目实现
—重点是评论时间的显示,向服务器请求返回时间不会是2021/11/23这种形式进项展示的,它是以Unix时间元年为起点,返回对应的时间戳;因此这里需要将时间戳转换为时间格式化字符串!
—时间戳转换为时间格式化字符串:
【1】将时间戳转换为Date对象:
const date = new Date(时间戳*1000)
,注意这里时间戳是以秒为单位,date
是以毫秒为单位!!【2】将
date
格式化转换为对应的字符串,因为转换十分常用,已经封装为一个函数,分别传入date
和格式化形式:fmt.format(date,'yyyy-MM-dd hh:mm:ss')
,其中y表示年份,M表示月份,d表示日,h(12小时制)/H(24小时制),m表示分钟,s表示秒钟;这里是Java中提供的一种转换方式,原生JS中没有提供,可以自己封装一个时间戳格式化转换函数或者使用插件jutils-src、dayjs;—在我们这个项目中,我们可以将时间戳转换为格式化字符串封装在过滤器中,在时间显示上使用过滤器进行时间戳转换;但是Vue3中已经移除了filters
-
详情页推荐栏的展示
项目需求:详情页中推荐栏的展示,类似于首页的推荐栏展示;
项目实现
—这里直接使用首页推荐栏的组件GoodList实现详情页的推荐栏展示,但是由于首页推荐栏组件进行了
@load
监听,图片加载完毕后通过事件总线向Home组件传递一个监听事件,而现在我们需要在详情页中图片加载完成后,将事件不应该传递给Home,在详情页下应该将事件提交给详情页;—思路一:通过判断当前活跃路由实现不同跳转:
imgLoad(){ if(this.$route.path.indexOf('/home')){ this.$bus.$emit('homeItemImagLoad') }else if(this.$route.path.indexOf('/detail')){ this.$bus.$emit('detailItemImagLoad') } }
—思路二:在首页离开的生命周期函数中取消首页中事件总线里图片监听事件,
this.$bus.off('itemImgLoad',this.itemImgListener)
,这里需要注意不能直接传入监听事件,这样的话就取消所有页面下的改监听事件,需要传入哪个函数下的监听事件进行取消;—
mixin
混入:官方表述,Mixin 提供了一种非常灵活的方式,来分发Vue组件的可复用功能。一个 mixin 对象可以包含任意组件选项。当组件使用 mixin 对象时,所有 mixin 对象的选项将被“混合”进入该组件本身的选项。因为这里首页和详情页都有使用图片加载监听事件,可以使用
mixin
混入实现抽取,完成组件复用能能; -
详情页导航联动效果
项目需求:点击详情页导航可以跳转到对应的页面,或者页面滚动到一定位置,跳转对应的导航标题,实现导航标题与内容的联动
项目实现
—点击标题,滚动到对应的主题内容:通过导航组件传递出来的点击事件,在点击事件中实现点击对应的导航标题,
this.$refs.scroll.scrollTo()
滚动到对应主题内容的位置,可以通过滚动条offsetTop
属性获取滚动位置;—获取滚动位置
offsetTop
的大小:这里需要在图片加载完毕获取滚动大小,【1】
created
函数中不能获取DOM元素,未挂载;【2】
mounted
函数中,挂载完毕DOM元素,但是数据未更新,数据获取不到;【3】在获取数据的回调函数也不行,因为DOM未渲染完毕;
【4】因此需要将计算函数放在
updated
生命周期函数中,此时数据更新完毕,完成虚拟的DOM的渲染和打补丁,组件DOM已完成更新,可以执行依赖DOM的操作,但是此时获取的依旧是图片未加载的数据;另外,需要注意,每次更新都需要清空数组,否则会将更新的数据不断拼接在数组后面;—
this.nextTick()
:无法直接在created
周期函数中获取DOM相关数据,如果要在此阶段实现DOM操作,要放在nextTick()
回调函数中,因为created
中初始化数据后,不会立即更新数据,需要进行渲染后在更新DOM, 因此无法在created
函数中获取到相关值,必须等到渲染完毕获取值, 可以使用nextTick
等到DOM渲染完毕回调函数;—需要注意:在上述
nextTick
中获取滚动位置依旧不正确,因为虽然拿到最新数据,DOM渲染完毕,但是图片依然没有加载完成,所以目前获取的是未加载图片的数据!!—最终获取高度:在图片加载完毕监听事件中获取
offsetTop
的值,这里可以对获取函数实现防抖操作,避免图片加载多次请求;滚动到主题内容,导航切换对应的主题项
—这里需要需要监听滚动事件,并通过判断当前滚动位置与对应的导航索引进行判断,实现主题项的切换;
—由
Scroll
组件传递出的滚动监听事件下,获取当前的y值,注意这里要取负值,因为滚动监听获取的值是负数;—对当前y值与对应索引进行映射,并通过
this.$refs.nav.currentIndex = this.currentIndex
将当前索引传递给导航下的索引;—判断条件,hack方案:在进行相邻区间判断时,为了防止遍历索引溢出,我们可以分两步判断,最后一项单独判断;但是这种判断很繁琐,因此可以在数组最后一项后面添加一个最大值
Number.MAX_VALUE
,将判断合并判断;for(let i = 0;i<this.themeTopYs.length-1;i++){ if((this.currentIndex !== i) && (positionY >= this.themeTopYs[i] && positionY < this.themeTopYs[i+1])) }
-
回到顶部混入封装
项目需求:因为返回顶部在首页和详情页都有用到,可以进行混合封装,实现组件的可复用;
项目实现
—将组件可复用功能和共同数据抽取h饿放置mixin.js文件中实现封装;