在学习了 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. 思维导图软件iMindMap的使用方法

    从手绘的思维导图再到各种各样的思维导图的软件,思维导图的高效性大家都体会到了.思维导图软件iMindMap在众多导图软件中是最受欢迎的之一,下面就给大家分享一下思维导图怎么画: 首先我要教给大家的是如 ...

  2. php进阶学习-单例设计模式

    什么是单例模式(singleton)? 在整个应用程序的生命周期中,任何一个时刻,单例类的实例都只存在一个,同时这个类还必须提供一个访问该类的全局访问点. 单例模式的特点 一个类只有一个实例 私有克隆 ...

  3. Linux 学习笔记01丨Ubuntu系统安装、配置及软件教程集合

    1. Ubuntu系统安装 Windows10安装ubuntu18.04双系统教程 Ubuntu 20.04.1 镜像下载 软碟通 机械革命进入BIOS模式 要按F2,注意将Boot Option中将 ...

  4. Java基础教程——接口

    接口 接口只是一种约定.--Anders 接口定义了一种规范--多个类共同的公共行为规范. 对于接口的实现者--规定了必须向外提供哪些服务 对于接口的调用者--规定了可以调用哪些服务,如何调用这些服务 ...

  5. Linux下的MediaWiki的部署启动遇到的问题与解决方案

    1. MySQL安装不成功 解决方案:https://bbs.csdn.net/topics/394377536 2. no space left on device ubuntu 解决方案:http ...

  6. java17(面向对象)

    1.面向过程:所有事情都是按顺序一件件做,未知主体 买菜,做饭,吃饭,洗碗 面向对象:将功能封装到对象之中,让对象去实现功能 去饭馆,告诉服务员要吃啥,然后等着端上来. 面向对象的目的: 复杂的东西简 ...

  7. Bootstrap Blazor 组件介绍 Table (三)列数据格式功能介绍

    Bootstrap Blazor 是一套企业级 UI 组件库,适配移动端支持各种主流浏览器,已经在多个交付项目中使用.通过本套组件可以大大缩短开发周期,节约开发成本.目前已经开发.封装了 70 多个组 ...

  8. Fiddler 4 断点调试(修改response请求参数)

    1.选择测试链接 2. 2然后点击规则的Automatic Breakpoints 的 After Responses 3.然后重新发起请求并找到链接 4.然后修改数据 5.最终效果

  9. 第11.2节 Python 正则表达式支持函数概览

    为了大家熟悉re模块匹配文本的处理,本节将概要介绍与此处理有关的几个主要函数,提供了如下主要函数: 以上函数中的部分的三个重要参数说明如下: pattern都是代表匹配规则的模式字符串,string代 ...

  10. 由Java 15废弃偏向锁,谈谈Java Synchronized 的锁机制

    Java 15 废弃偏向锁 JDK 15已经在2020年9月15日发布,详情见 JDK 15 官方计划.其中有一项更新是废弃偏向锁,官方的详细说明在:JEP 374: Disable and Depr ...