在学习了 vue 之后,决定做一个小练习,仿写了一个有关购物商城的小项目。下面就对项目做一个简单的介绍。

项目源码: github

项目的目录结构

-assets                            与项目有关的静态资源,包括 css,以及一些 images

-common                            公共的工具类方法

-components						   公共组件
-common 与项目耦合度较低的组件
-content 与项目耦合度较高的组件 -network 网络请求相关 -router 路由相关 -store vuex 相关 -views 主要展示的页面
-home 首页
-childcomps
-detail 详情页
-childcomps
-cart 购物车页面
-childcomps
-profile 个人信息页面
-childcomps

划分好目录结构后就可以对每个模块进行独立开发

主要实现的功能

首页
  1. 顶部轮播图的展示
  2. 中间选项卡点击可进行商品的切换以及吸顶效果
  3. 点击商品进入商品详情页
  4. 上拉展示更多商品
  5. 点击按钮回到顶部
详情页
  1. 根据首页中用户的点击进行每个商品的独立展示
  2. 点击商品信息对应的标题跳转到对应的内容区域
  3. 滑动页面过程中与顶部商品信息的标题联动效果
  4. 点击按钮回到顶部
  5. 加入购物车跳出弹窗
购物车页面
  1. 展示各种商品的数量
  2. 底部工具栏展示选中商品的总价格
  3. 全选与取消全选
  4. 结算时的两种弹窗
我的页面
  1. 个人信息的展示
  2. 点击我的购物车进入到购物车页面

主要思路介绍

底部 tabbar 的封装

移动端中比较常见的一种导航栏,需要根据用户的点击进行跳转到相应的页面,所以直接封装一个公共的组件。布局一般是图片加文字,图片一般有两种,需要根据当前是否处于活跃状态的路由和用户的点击来判断展示哪张。内部预留插槽,用户根据实际需求选择底部导航的个数。每个导航为其配置路由。

顶部导航 navbar 的封装

顶部的导航基本会出现在每个页面中,所以也直接封装为一个公共组件,布局通常是左中右三栏布局,所以组件内部预留三个插槽,采用 flex 布局。

数据请求

对 axios 再封装为一个 request.js 文件,让所有的页面都基于这个文件发送请求,这样做可以避免重复操作,提高了项目后期的可维护性。

在这个项目中将每个页面需要发送请求的部分又进行了一层封装,即每个页面都有独立的与之相对应的发送请求的文件,首页发送请求只需要面向 home.js,详情页发送请求面向 detail.js。

滚动组件 Scroll

  • 引入 better-scroll 来替换掉页面的原生滚动,Scroll.vue 是对 better-scroll 的封装,为了提高组件的可复用性,可以让 probeType, pullUpLoad,等值从外部传入(项目中 click 的值为 true)。
  • Scroll.vue 内代码的封装:

    创建一个 Better-Scroll 对象,传入 DOM 和 参数( probeType,click,pullUpLoad等),

    监听 scroll 事件,该事件会返回一个 position,

    监听 pullUpLoad 事件,表示该事件触发的时候是否上拉加载更多,

    封装一个滚动的方法 this.scroll.scrollTo(x,y,time),

    封装一个刷新的方法 this.scroll.refresh(),会重新计算可滚动区域的高度,

    封装完成上拉加载更多的方法 this.scroll.finishPullUp

全局插件 Toast

  • 项目中有两个地方用到了弹窗组件,一个是点击加入购物车时,一个是点击结算时,如果想要使用弹窗组件那么每次都需要导入还要加一些代码,这样做有点麻烦,如果有多个地方都需要使用这个弹窗组件那么此时需要做的重复工作量太大,所以采用 Vue.use() 方法全局注册了一个插件。
  • 需要在 main.js 中 import, 然后 Vue.use() 进行注册,Vue.use() 需要传入至少一个参数,该参数只能是 Object 或 Function ,如果是 Object 那么这个对象需要定义一个 install 方法,如果是 Funcion 那么这个函数就被当做 install 方法,在 Vue.use() 执行时 install 方法会默认执行,install 方法调用时会将 Vue 作为参数传入。Vue.use() 除了传入第一个参数外,也可继续传入一个选项对象。这里还要注意的是 Vue.use() 必须要在 new Vue() 之前被调用,这是因为在安装组件时,组件给 Vue 添加全局功能,所以必须写在 new Vue() 之前,否则创建的 Vue 实例就无法获取插件添加的全局功能。
  • 所以我们在项目中使用了 Vue.use() 注册了全局插件,在任何地方想使用只需要 this.$名称 即可。

首页

  • 数据处理

    banners 数组保存轮播图的数据,recommends 数组保存推荐的数据。

    还有其它的即需要展示的每一条商品的数据通过 goods 来保存。

    goods: {

    'pop': {page: 0, list: [ ] },

    'new': {page: 0, list: [ ] },

    'sell': {page: 0, list: [ ] }

    }
  • 最上面的轮播图,可以根据图片数量自动进行轮播,也可手动滑动图片,是一个独立的子组件。

    轮播图下面的推荐部分是一个独立的子组件。
  • 对 goods 中的数据进行展示,封装 GoodsList 组件,而每一个商品又是一个独立的小组件 GoodsListItem.vue。
  • 点击选项卡进行数据的切换,监听选项卡的点击事件,通过 $emit() 发出事件(携带 index),在父组件中监听,根据 index 对应的数据类型(swicth(index)),父组件再通过 props 将 currentType 传给 GoodsList 进行展示。
  • 滑动过程中选项卡的吸顶效果,原理是复制一个选项卡(tabControl)在顶部,默认隐藏,通过 v-show 来决定何时出现,用一个变量保存原选项卡 (contentControl) 的 offsetTop,在页面滚动的过程中不断获取滚动的距离,当滚动的距离大于原选项卡 (contentControl) 的 offsetTop时,就显示 tabControl。
  • 上拉加载更多,Scroll 组件中的 pullingUp 一触发就会发送一个事件,父组件中进行监听然后当事件触发的时候去请求数据即可。
  • 回到顶部组件 BackTop,默认不显示,当页面滚动到设定的距离时显示。点击回到顶部需要监听组件的点击(@click.native),然后触发函数 scrollTo(x,y,time) 返回顶部。

详情页

  • 当用户点击商品时进入到详情页,首先要监听每个 GoodsListItem 的点击,点击时进行路由的跳转,并且携带商品的 id,根据 id 请求数据,再将数据进行展示。
  • 底部功能栏的封装也是一个独立的子组件,当点击加入购物车时,将点击事件发送给父组件 detail.vue,父组件中根据商品 id 获取购物车(cart.vue,与 detail.vue 同级)中需要保存的商品数据,提交到 vuex 进行全局状态管理,购物车组件中通过 $store.state 拿到数据进行渲染,加入购物车成功后弹出弹窗提示。
  • 将商品添加到购物车其实有两种情况,一种是 vuex 中还没有这个商品的添加,另一种是 vuex 中已经有了这个商品,所以为了使 mutation 里定义的函数职能单一,这里将点击添加购物车这个操作提交到 action 中管理,再由 action 提交到 mutation 来使 vuex 管理的状态进行更新。
  • 点击联动效果,商品详情页面中共有四个部分组成:商品,参数,评论,推荐,每个部分都是一个独立的子组件,当数据请求完成时去获得每个组件的 offsetTop ($refs.组件绑定的 ref 值.$el.offsetTop) 保存在一个数组中,监听商品详情栏中的点击,根据 index 触发 scrollTo() 进行跳转
  • 滑动联动效果,实时监听滚动位置,通过和上面数组中的值进行比较,在 0 - 参数之间的偏移这个高度时,currentIndex 为 0,在参数的偏移高度 - 评论的偏移高度时 currentIndex 为1,以此类推,这样就可以实现在滑动的过程中与顶部标题信息的联动。
  • 回到顶部,与首页中的一样。

购物车页

  • 渲染在详情页添加到购物车的数据,从 vuex 中拿到数据,封装 CartList 组件,而每一条商品又是一个独立的子组件 CartListItem。
  • 底部工具栏的封装,主要包括全选按钮,选中商品的总价格,去结算时的弹窗。
  • 全选按钮的实现,某商品第一次添加到购物车时,需要给这件商品的数据里定义一个是否选中 (checked)的属性,默认为 true。为了管理选中的状态,只能由 mucation 对状态进行修改,商品最终是否展示也由 mucation 最终修改的状态为准,监听全选按钮的点击,根据商品数组中每个商品的 checked 属性进行逻辑判断即可。
  • 点击去结算组件时,先判断当前购物车的商品列表中是否有数据,如果没有弹出提示信息,让用户选中商品。

我的页面

  • 展示用户的一些个人信息,点击“我的购物车”跳转到购物车页面,this.$router.push('/cart')

项目中遇到的一些问题

由于引入 better-scroll 带来的问题
  • 引入 better-scroll 之后,带来了一些问题,比如页面会划不动、scrollTo 跳不准、等等,导致这些问题的原因,多数情况下是因为请求的数据没回来,或者拿到数据了但是页面还未加载完,而 better-scroll 在这之前就需要计算可滚动区域的高度,但由于图片还没加载完所以这个时候计算的高度并不是最终的高度,所以导致滚动出现了问题,怎么解决呢?
  • 那么这个时候可以在某些资源加载完成是时来个 scroll.refresh(),让 better-scroll 重新计算可滚动区域的高度,比如项目中我们可以监听图片加载事件,当有图片加载完成时就触发 scroll.refresh()。但这样的话只要一有图片加载完成就会 scroll.refresh() ,使得 refresh() 的调用太频繁了,在此我们可以进行一个防抖操作来减少 scroll.refresh() 的调用。
让首页的内容保持原来的位置
  • 项目中在浏览到首页某个位置时,用户点击了商品然后进入了商品详情页或者进入了购物车等其它页面,当再次回到首页时发现不是之前浏览的位置。
  • 可以在首页的 deactivated() 中记录下离开时的位置信息,activated() 时再将位置设置为原来保存的位置。
选项卡 tabControl 的吸顶效果
  • 其实实现这个效果的基本思路就是首先获取 tabControl 的 offsetTop ,怎么获取?this.$refs.tabControl.$el.offsetTop ,然后实时监测选项卡的滚动位置,当滚动位置达到 offsetTop 时将选项卡改为固定定位即可,这里需要注意的是在 mounted() 中获取的值不一定是正确的,因为可能顶部的轮播图或者推荐部分的图片没有加载完,那么如何获取正确的值?监听轮播图的图片加载情况,加载完毕发出事件,然后在首页中再去获取 offsetTop。
  • 按照这样的思路实现以后,发现并没有达到预期的效果,而是出现了下面的商品部分会突然上移,并没有实现停留的效果,所以换了另一种方案,就是上文提到的先在顶部复制一份占位选项卡,默认不显示,然后根据滚动位置和 offsetTop 来决定什么时候显示,这样就实现了吸顶的效果。

vue 实现一个商城项目的更多相关文章

  1. 「开源」SpringCloud+vue搭建的商城项目

    最近在研究SpringCloud,看到一个基于SpringCloud+vue搭建的模拟商城项目.用来辅助学习SpringCloud企业级开发还是很有帮助的.强烈推荐!! 源码地址在最后. spring ...

  2. 使用Vue创建一个新项目

    1.环境 保证已经安装好了node\npm\vue等工具,将路径设置为想要建立新项目的文件夹路径 2.关于npm与cnpm npm包管理器,是集成在node中的,node环境安装完成,npm包管理器也 ...

  3. Vue+Spring Boot 前后端分离的商城项目开源啦!

    新蜂商城 Vue 移动端版本开源啦! 去年开源新蜂商城项目后,就一直在计划这个项目 Vue 版本的改造,2020 年开始开发并且自己私下一直在测试,之前也有文章介绍过测试过程和存在的问题,修改完成后, ...

  4. Vue3 来了,Vue3 开源商城项目重构计划正式启动!

    我打算用 Vue3 写一个商城项目,目前已经开始着手开发,测试完成后正式开源到 GitHub,让大家也可以用现成的 Vue3 大型商城项目源码来练练手. Vue 3.0 来了,我们该做些什么? Vue ...

  5. django 商城项目之购物车以及python中的一些redis命令

    最近在用django restframe框架做一个商城项目,有一个关于购物车的业务逻辑,是用cookie和redis存储的购物车信息,在这里记录一下. 完成一个商城项目,如果不做一个购物车,就是十分可 ...

  6. Vue3教程:一个基于 Vue 3 + Vant 3 的商城项目开源啦!

    之前发布过一篇文章,告诉大家我要开发一个 Vue3 的商城项目并开源到 GitHub 上,供大家练手和学习,随后也一直有收到留言和反馈,问我开发到哪里了,什么时候开源之类的问题,今天终于可以通知大家, ...

  7. 用vue开发一个公众号商城SPA——1.前期准备和写页面

    使用vue开发公众号商城 第1篇记录项目准备.搭建,写页面遇到第问题以及总结,持续更新 公司最近接了个商城项目,包括PC端商城.微信公众号网页商城.后台管理系统.这几天在做微信公众号商城,又新接触了很 ...

  8. Vue Create 创建一个新项目 命令行创建和视图创建

    Vue Create 创建一个新项目 命令行创建和视图创建 开始之前 你可以先 >>:cd desktop[将安装目录切换到桌面] >>:vue -V :Vue CLI 3.0 ...

  9. Vue nodejs商城项目-项目概述

    项目概况 用vue2.0 +node.js +MongonDB 做了一个商城系统 技术选型 Vue2.0+node.js+express+MongoDB+axios+vuex 构建工具 Webpack ...

随机推荐

  1. FL Studio 插件使用技巧——Fruity Reeverb 2(下)

    了解大教堂声场的特点 上节教程中我们说到,混响具有营造空间感的作用.当我们想要在FL Studio软件中用Fruity Reeverb 2 插件有目标地模仿一个特定空间的环境时,我们需要充分了解该空间 ...

  2. 如何使用ABBYY FineReader 用户词典识别专业术语?

    ABBYY FineReader 15可以说是比较新的版本,在这个版本中能运用强大的光学字符识别技术对PDF文档扫描件.图像等文件进行OCR识别.在识别的过程中,会使用其内置的词典检查识别文字,以获得 ...

  3. Netty源码分析之ByteBuf(二)—内存分配器ByteBufAllocator

    Netty中的内存分配是基于ByteBufAllocator这个接口实现的,通过对它的具体实现,可以用来分配我们之前描述过的任意类型的BytebBuf实例:我们先看一下ByteBufAllocator ...

  4. Java之 函数(五)

    第一部分 : IDEA开发工具 1.数组 1.1 数组介绍 ​ 数组就是存储数据长度固定的容器,存储多个数据的数据类型要一致. 1.2 数组的定义格式 1.2.1 第一种格式 ​ 数据类型[] 数组名 ...

  5. open()和with open() as的区别

    2020-03-18  20:37:55 open()和with open() as的区别 1 file = open("test.txt","r") 2 fo ...

  6. 第四代Express框架koa简介

    目录 简介 koa和express koa使用介绍 中间件的级联关系 koa的构造函数 启动http server 自定义中间件 异常处理 简介 熟悉Spring MVC的朋友应该都清楚Spring ...

  7. CentOS下如何用nmon收集系统实时运行状况

    #赋予执行权限 chmod +x nmon 执行./nmon可以查看实时的系统状态有提示的,d看磁盘,n看网络,c看cpu #如果不想看实时的,想收集系统长时间运行情况然后分析,可用这个 nohup ...

  8. java40

    时隔小半年,重新捡起Java的学习 问题: 1.eclipse好久没用,再打开时,eclipse的项目都没有了,如何找回? 打开switch-workplace-other点开,选择以前的文件所在处. ...

  9. 【五校联考1day2】JZOJ2020年8月12日提高组T2 我想大声告诉你

    [五校联考1day2]JZOJ2020年8月12日提高组T2 我想大声告诉你 题目 Description 因为小Y 是知名的白富美,所以自然也有很多的追求者,这一天这些追求者打算进行一次游戏来踢出一 ...

  10. JZOJ8月10日提高组反思

    JZOJ8月10日提高组反思 T1 没想到怎么打 就去打暴力了 本来想拿个30不错了 结果\(AC\)了 话说回来,数据也挺小的 T2 不AC便爆0 就一个数据点 给不给打暴力的人活了 正解是状压DP ...