仿写购物商城

vue脚手架仿写购物街项目

线上

支持移动端访问(同局域网且知道电脑IP)

更新:

  1. 补上轮播图的坑
  2. 购物车组件新加增减商品数量的按钮
  3. 上传vue脑图

项目目录结构

-assets                   图片和初始化页面的基础样式
    -css
    -images

-common                   封装的可以公共使用的一些工具方法

-components               公共组件
    -common               与项目无耦合的组件
    -content              与项目耦合较高的组件

-network                  网络请求相关(对Axios的再封装)

-router                   路由相关

-store                    vuex状态管理相关

-views                    主要展示的页面
    -cart                 购物车页面
        -childComps
    -category             商品分类页面
        -childComps        
    -datail               商品详情页面
        -childComps
    -home                 首页
        -childComps
    -profile              我的
        -childComps

主要实现的功能

首页

  • 头部轮播图片部分,可根据图片数量自动生成进行自动轮播和滑屏轮播的轮播图
  • 中间选项卡部分实现吸顶和切换选项功能
  • 上拉展示更多数据
  • 点击商品进入商品详情页
  • 回到页面顶部功能按钮

分类页

  • 将请求回的数据重定义数据结构,然后将数据进行分级展示
  • 中间选项卡部分实现吸顶和切换选项功能
  • 点击商品跳转到商品详情
  • 回到页面顶部功能按钮

购物车页

  • 展示每件商品数量、各种商品的数量
  • 全选功能完善、计算选中商品总价格
  • 结算时的两种弹窗

商品详情页

  • 完成数据展示
  • 上拉页面与商品详情页的标题联动
  • 加入购物车跳出弹窗等功能
  • 回到页面顶部功能按钮

我的页面

  • css样式页面展示

运用到的包或封装的工具方法

  • BetterScroll
    替换掉所有可滚动页面的原生滚动,(商品分类页面有两个滚动)

  • Axios
    对axios进一步封装require,让所有请求对该文件进行依赖,防止对axios过度依赖

  • Mixin
    让代码复用性更高

  • PostPxToViewport
    移动端页面适配

  • Toast
    封装的弹窗组件

  • FastClick
    解决移动端点击事件的延迟问题

主要思路介绍

请求相关

  1. 对axios进行再封装为一个require文件,让所有页面都依赖这个文件发送请求,防止以后axios不维护时,就要对所有依赖axios包的页面都需要进行更改的情况,而封装后就只需要修改require文件就可以,既省时又高效;
  2. 这里还对每个页面的发送请求的部分又进行了一次封装,使得每个页面有专门发送请求的文件,也可在这个文件中定义用于保存请求回来的数据的一个对象类,通过传入参数并且new后,页面就可获取到数据。方便代码维护。

轮播组件

  • 这个组件我猜测并不是完整版的,模板里多预留了一个没有用到的插槽,而用到的那个插槽也是可以不要的,组件下面我注释的应该是一个点击轮播功能的实现代码,但并没有元素去触发它们。

    • 轮播完整功能有4个

      1. 默认自动轮播,首先需要获取要轮播的元素且数量要大于一,让最前面和最后面的两个元素分别再克隆一个元素,让新添加的元素插入最前和最后的位置,默认显示的元素为新添加的在最前位置的元素,元素的索引为1。然后用css3属性让轮播条进行轮播运动,当索引大于要轮播元素的数量时,向左的轮播运动会越界,因为存在在最后位置的克隆元素,虽然不会报错,但是需要让元素循环轮播,索引回正。

      2. 滑屏轮播,当元素正在轮播时,不可拖动元素(处于轮播的时间间隔里才能拖动),在拖动的前一刻记录下当前轮播条到视口的距离,在放开元素的前一刻再记录下当前轮播条到视口的距离,求出轮播条真正移动度距离,当这个距离与视口宽度的比值大于某个值时,才进行一次轮播运动

      3. 点击轮播(猜测),点击两侧的按钮,修改元素索引进行轮播。

      4. 小圆点轮播,选中的小圆点与展示在视口的元素的索引同步。

    图解

头部导航栏组件

  • 头部导航栏在页面中非常常见,而且布局(左中右)也非常相似,所以只要运用插槽让头部导航栏就可以更具有扩展性

底部导航栏组件

  • 一般出现在移动端较多,布局多以图片加文字,多数具备点击跳转页面功能,所以也用插槽来进行扩展,并为其绑定路由。当那个地方被点击就路由到那个页面并切换点击位置上的图片,由于切换图片的位置相同,就需要将两张图片都绑定一个插槽,然后根据当前处于活跃的路由的路径与由点击传过来的路径是否相同,来判断那张图片进行展示,注意:v-if等判断语句最好在每个slot标签外部另外嵌套的标签上定义,防止v-if等判断语句被替换

栅格组件

  • 在分类页的二级菜单栏有用到,根据传入的列数(竖)和每列宽度、行数(横)和每行宽度等四个值来使二级菜单进行自动布局,虽然传进来四个值,但用到的只有两个,以项目为例,传入的是3列,每列高150px,需要展示的子级们有三列,所以自己的宽度为将父级的宽度除3,高度为150px,注意:如果有进行移动端页面适配时,需要将所有的px像素单位转为vw或vh的像素单位。取视口的宽高分别除100就得到1vw等于多少px的宽度,1vh等于多少px的高度。然后将px像素转为vh和vw的像素,老师就是用来postcss-px-to-viewport插件而没有转换像素单位,所以在视频中只展示两行二级菜单

选项卡组件

  • 该组件主要实现的是点击选项切换展示的数据 当点击某一个选项后,选项卡组件就将这个选项的索引通过$emit发送自定义事件给父组件。父组件再通过v-bind将数据传给子组件的props里,子组件拿到数据后渲染页面

商品详情页面

  • 当点击页面的某一个商品时,通过路由并且需要传入该商品的id跳转到category页,请求数据然后布局渲染,

添加商品到购物车

  • 当点击商品详情里的添加购物车时,将子组件的的点击事件通过emit发送到父组件商品详情页中,父组件收集购物车需要展示的信息后将数据提交到vuex中进行全局状态管理(这里的父组件是商品详情页,而购物车组件与他同级),购物车组件通过$store.state来拿到数据并渲染,项目中是将拿数据操作定义在vuex里的getters中,再映射到购物车组件中拿到数据,渲染数据,并展示弹窗

vuex状态管理

  • 在这个项目中,只有将商品详情页里的数据添加到购物车有用到vuex进行了状态管理,以他为例,将商品添加到购物车有两种添加商品的职能,一个是vuex中还没有这个商品的添加,另一个是vuex中有这个商品的添加,而为使mutation里定义的函数职能单一就需要将点击添加购物车这个操作提交到actions中管理,再由action提交到mutation来使vuex管理的状态进行更新。更新完毕,展示弹窗。

购物车全选按钮

  • 首先在某商品第一次添加到购物车时,需要给这件商品的数据里定义一个数量1,一个是否选中true的属性,为了管理选中的状态,只能由mucation对状态进行修改,商品最终是否展示也由mucation最终修改的状态为准,所以就可以根据每件商品在statr保存的这个属性是true还是false来判断是否选中,然后进行全选全不选等一些逻辑判断

  • 在购物车中对商品进行加减也要如此进行

弹窗组件

  • 封装弹窗

    • 首先要创建一个.vue文件来定义弹窗的样式、展示规则等,再在同级目录下创建一个index.js文件来对封装的插件进行依赖,注意:这里在vue原型上定义的$toast方法需要Toast.vue文件被组件构造器new后(即被解析后),才能将Toast.vue中的methods里的方法函数识别并定义到vue原型上,这块与老师视频里不一样。
  • 运用弹窗

    • 在项目中,有两个操作会触发弹窗,一个是点击添加购物车按钮,另一个是购物车组件里的支付按钮;支付弹窗好说,点击支付,只要判断当前有无商品被选中来分别跳出弹窗就可以了。而点击添加购物车是有个流程:点击————>action———>mutation,根据vuex官方解释action通常是异步的,所以为了稳妥起见可以用promise来监听添加购物车这个操作完成,在执行弹窗操作this.$toast.show(‘加入购物车成功~~’, 展示时间)。

Scroll组件

  • 介绍

    • better-scroll是一个基于iscroll的使滚动更加流畅的插件,而Scroll组件是对better-scroll的再封装
  • 封装

    • 为了更好的复用,可以让click、probeType、pullUpLoad的值都由外部传入,在项目中click的值为true,其它两个由外部传入。

    • 绑定和发送事件:监听实时滚动的scroll事件要将实时的Y位置通过 e m i t 发 送 出 去 , 监 听 元 素 滚 动 到 底 部 的 p u l l i n g U p 事 件 也 通 过 emit发送出去,监听元素滚动到底部的pullingUp事件也通过 emitpullingUpemit发送出去。

    • 定义锚点函数(scroll.scrollTo(x, y, time)的封装)、每次上拉都能触发pullingUp的函数(scroll.finishPullUp()的封装)、重新计算content区高度的函数(scroll.refresh()的封装)、获取当前时刻content元素的位置函数(注意:该函数的执行体只执行一次,由scroll.y封装)

  • 上拉页面联动效果

    就拿商品详情页头部的商品、参数、评论、推荐来举例
    • 首先在子组件头部导航栏中实现联动的点击事件(商品、参数、评论、推荐这几个点击按钮)和被点击后的样式(根据索引展示样式),获被点击取按钮的索引并通过$emit发送到父组件商品详情页里。

    • 获取理想状态里的商品、参数、评论、推荐在页面的高度(不是获取在导航栏里的这几个按钮的高度)并保存到数组中(现实中获取的不对)

    • 点击联动:

      • 父组件接收封装的Scroll组件传来的scroll事件和当前的高度并把probeType的值传给子组件Scroll,一般传的都是3,只要content元素动了就给我监听。

      • 例如点击参数按钮就找到之前保存高度的数组里根据到参数的索引的高度值,通过scrollTo跳到高度值的位置

    • 滑动联动:

      • 通过Scroll组件传来的实时的高度与商品、参数、评论、推荐在页面的高度进行对比(0-参数的高度之间的范围为0,参数的高度-评论的的高度之间的范围为1,评论的高度-推荐的的高度之间的范围为2,推荐的高度-Number.MAX_VALUE为3)再把0、1、2、3的某个数对通过$refs拿到子组件里的data里的currIndex进行赋值,这里做了个简单的防抖,如果scroll获取的高度在上面数组记录的两个高度之间时,就不对子组件里的data里的currIndex进行赋值。
  • 吸顶效果

    • 与上面的上拉联动做法类似,要接收传来的scroll事件和当前的高度并把probeType的值传给子组件,以首页的选项卡为例,原理就是复制一个选项卡,让复制的选项卡吸顶给他fixed定位并用v-show让他隐藏。首先要获取原选项卡的高度,当content元素高度大于或等于原选项卡的高度,就让复制的选项卡展示
    • 由于有两个选项卡,就会有不同的点击后展示效果,而要想把吸顶效果做的天衣无缝,就必须然他们两个展示的效果相同,做法也简单,因为吸顶的选项卡是复制过去的,所以他们共用一个由子组件传来的自定义事件的执行函数,就可以让他们在这个函数里用$refs选中元素获取currIndex,让子组件传进来的index对currIndex进行赋值
  • 上拉加载更多数据效果

    • 父组件接收封装的Scroll组件传来的pullingUp事件,该事件一触发,就去发送请求补充数据,然后渲染,由于有数据要补充,所以就得有个好的保存数据的结构👇
  • 回到顶部小按钮

    • 理解了前面的点击联动,这个做起来就简单了点击按钮后触发scrollTo(0, 0, 传个时间)
  • 在页面切出,当切回时原页面的位置不变

    • vue中有activated来监听页面处于活跃状态(页面被打开或切入)和deactivated监听页面被关闭或切出的,只要在页面切出用scroll.y记录当前的高度,切入时用scrollTo调到记录的位置就行了,注意:虽然浏览器对页面进行了缓存(以home页为例),但是也需要将缓存的页面渲染出来,当页面渲染慢了点就会跳不准。有可能连元素都获取不到。
  • 由于引入better-scroll带来的问题

    • 比如划不动、scrollTo跳不准、没有scroll这个方法等等,导致这些问题的原因有很多,页面未加载完成、请求的数据没回来,回来了没渲染等等,但有个办法可以解决掉大部分的问题,那就是在获取高度前来个scroll.refresh(),图片都加载成功来一个,打开被切出的页面后在跳到切除的高度前来一个,剩下的就只要对this.scroll是否存在进行判断
    • 以加载图片为例,通过监听给每张图片绑定load事件,当有图片回来就被触发,而且是有一张就触发一次,然后用个防抖函数或者某个部分的图片加载过半就scroll.refresh(),

非父子组件的通信-事件总线

  • 非父子组件通信可以用vuex,但在这个项目中用到的是$bus,只是用于发送某部分的图片加载完毕的事件,就不用vuex这把牛刀

存储数据的方法

  • 请求回来的是所有数据数据

    • 最简单的数组对象就可以搞定,然后遍历数据渲染出来

    • 复杂有嵌套请求,以项目的分类页数据为例,首先请求的是子菜单里的标题数据(第一级),然后请求右上部的数据(第二级),完了之后立即分别请求右下部的三个按钮里的数据(第三级),老师的做法简单讲就是{index:{ {}, {} }},第一级的数据数量是确定的16条里面的两个对象一个放第二级的数据,一个放第三级数据,第三级里又分有3个数组相对应pop、new、sell总的结构为{ index: { {}, { [pop], [new], [sell] } } },最外侧的对象里有16条数据,index指的是代表0-15的变量。

  • 请求回来的数据只有一部分

    • 以首页展示的商品数据为例这种情况就需要上拉通过发送请求来添加数据,一般利用分页来保存数据(后台也是通过分页的格式来响应数据),即:{‘pop’: {page: 页码, list: [数据]}, ‘new’: {page: 页码, list: [数据]}, ‘sell’: {page: 页码, list: [数据]}}。底部上拉发送请求,然后通过switch(选项卡的索引)来决定往那个地方push数据。

最后一次更新

购物车页面中添加商品数量按钮功能图片
购物车页面中添加商品数量

vue脑图
传不了xmind格式的文件,会在我的资源里分享出来

vue的生命周期
vue的生命周期

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值