个人项目之一个基于Vue技术栈的购物商城的单页面应用
这是关于使用vue技术栈(core+vue-router+vuex )做购物商城(仿蘑菇街)app项目的笔记。
个人项目源码:https://github.com/xinkuiwu/supermall
个人项目之一个基于Vue技术栈的购物商城的单页面应用
注:本项目是根据codewhy的vue项目,一步步自己手码出来的项目,并修改了一些bug,欢迎相互交流~
个人项目源码:https://github.com/xinkuiwu/supermall
关键词
JavaScript,Vue,路由切换,父子组件通信,状态管理,网络数据请求,CSS设计
项目总览
本项目主要能实现购物商店的基本操作,如浏览商品种类及商品的详细信息,包括商品价格,参数,评论,相关推荐等并且能把商品添加在购物车,可自选或全选地将商品进行结账等功能。
项目前期准备是使用vue CLI3进行文件目录结构的生成,包括源码路径,文件资源路径,视图路径等等。此外,我还对其他一些文件进行目录管理,包括区分公共组件和业务组件,视图组件和其子组件等,目的是为了更好地以封装化思想实现组件的合理复用。
项目分为五个视图模块:主页,商品详情页,分类页,购物车,个人页,并且通过vue-router进行视图切换和vuex进行一些状态管理。
主页
主页如图所示:
主页布局从上至下,由轮播图组件,推荐商品组件,导航栏组件和商品展示组件组成。最后使用Better Scroll滑动组件包裹。
其中导航栏组件与商品展示组件存在数据通信,即点击“流行”展示的是“流行的商品”,点击“新款”的商品展示的是“新款的商品”,这属于子组件(tabcontrol)监听点击事件,把子组件数据传出去,通过$emit(发布事件,参数)把参数传到父组件(home.vue),通过监听这个发布事件。通过监听,改变不同的商品展示索引值,从而控制展示不同的商品。
此外,还有这个’流行’, ‘新款’, ‘精选’的导航栏吸顶设计。我们还得监听滚动的位置,方便我们设置回到顶部按钮。上拉懒加载商品数据等。使用keep-alive包裹router-view,配合使用activated()和deactivated()来使得home离开时记录状态和位置。
Debug优化:通过监听异步加载完图片的方法,刷新滑动组件,来解决滑动异常的问题(原因在于滑动组件计算可滚动高度计算误差)。刷新频繁的防抖动函数处理。
知识点总结:组件,父子组件间通信,事件监听,周期函数钩子,封装思想,防抖debounce,事件总线(vue实例原型定义一个bus,事件总线有点类似vuex,但其是管理事件的。GoodItem发射一个事件(this.$bus.$emit(“事件1”))给事件总线,Home组件监听这个发射过来的事件(this.$bus.$on(“事件1”,function(){}))从而控制执行别的函数(Scroll的方法)。注意:默认情况下是没有$bus的,需要我们去改vue的原型,让$bus就是一个vue实例。)。
商品详情页
在首页中,点击某商品,页面会转至商品详情页,当我们点击加入购物车,就会加入到购物车页中,并且页面浮动显示“添加了新的商品”的消息),如图所示:
点击加入购物车提示加入成功,使用弹窗(Toast组件)提示。
除了除了商品本身图片,还可以点击参数,评论,推荐等导航,跳转到对应部分,展示信息。
商品详情页主要由商品展示组件,参数组件,评论组件,其他商品推荐组件组成。
其中,展示的商品详情由跳转路由,并根据携带的id信息,进行对应的数据的请求。
在真实服务器中,电商后台给的数据非常多而且繁杂,需要我们在写组件使用数据的时候,先整合好成一个对象(封装),然后在传给组件(组件面向这个对象)。
由于我们在home.vue使用的mounted的部分代码与Detail.vue使用的mounted的部分代码完全一致,所以可以使用mixin技术将其代码进行抽离。
vue官网也有mixin的说明:mixin也是一个钩子,并在调用组件自身的周期钩子之前被调用。
监听购物车按钮,发送事件出去。(子传父)获取购物车的相关消息。封装到一个对象里面。这个对象可以通过Vuex进行保存管理(可以在多个界面进行共享),购物车组件使用这个对象。注意不能够使用中央事件总线,因为组件在没有创建(点击详情页)时,这个对象是不存在的,购物车也就不能获取了。
Vuex中的代码重构:首先,mutations唯一的目的就是修改state中状态,mutations中的每个方法尽可能完成的事件比较单一一点。(单一职责原则(软件设计原则之一))devtools不好追踪对象状态。所以,有判断的操作,一般都是先放在actions里面,通过actions去修改mutations。(也就是说actions里面不一定只能放异步操作的东西)
bug:keep-alive会使得我们每次点不同商品的详情页都是显示同一个(第一个点的)商品的详情页。所以使用keep-alive的exclude属性,把Detail组件排除
知识点:动态路由(跳转进去的时候,需要传递参数例如图片id),时间格式转换(JS中需要调用第三方函数,才有这个时间格式化函数(是用正则表达式写的)),Toast,mixin混入技术(两个组件公用一段代码(不仅是函数,对象都行)),Vuex,单一职责原则。
分类页
分类功能主要是展示一些商品的分类,并且可以根据不同类别,展示不同的商品,如图所示:
分类页主要由两个模块组成:类别菜单组件和对应商品展示组件。具体设计和首页类似。比较简单。
购物车
物车显示了刚刚我们添加的商品并且计算好对应价格;此外,还可以添加多个商品并且可以手动选择自己想要的那几个或者点击全选,全部都选。如图所示:
获取购物车的商品个数,把这个方法封装一个getters文件里面。但是这样写的话,反倒是不如直接定义计算属性了。所以想做成,能直接使用getters当成计算属性。这是vuex提供的辅助函数mapGetters(直接从vuex导入)。
监听组件的点击,.native的方式。
知识点:vuex辅助函数mapGetters,.native。
个人页
个人页如图所示:
个人页是一些CSS样式的布局和一些图标引用,可视化地显示用户信息,包括用户余额,积分及其他信息等。比较简单,后续我们可以扩展相关功能,如用户信息管理系统等等。
项目代码和性能的一些优化策略
本项目除了实现上述的基本功能,还做了一些优化策略,例如文件路径取别名,返回页面顶部功能、Better-Scroll组件滑动优化、上拉加载优化、懒加载等。
在移动端的优化技术:
1、fastclick减少点击延迟
移动端的开发经常需要监听用户的双击行为,事件的发生顺序是这样的:touchstart—touchmove—touchend,然后大约过300ms触发click事件,用来判断是否有双击事件。
首先,安装fastclick (npm install fastclick –save)
然后导入,调用attach函数使用。
2、vue-lazyload框架,图片懒加载(移动端需要)
图片需要显示在屏幕时,才加载。(有些公司需要,有些公司不想要)(个人感觉不好~)
首先,安装(npm install vue-lazyload –save)
然后导入,使用,通过修改img:scr -> v-lazy
3、px2vw-css单位转化插件(webpack插件)
视口单位:
1.vw:1vw等于视口宽度的1%。
2.vh:1vh等于视口高度的1%。
之前我们写的CSS代码基本以px作为单位的,在移动端,当不同设备(设备高宽度不同,一般以iPhone 6位设计稿),可能会影响原设计的视感。所以需要把px转为vw。所以需要一个工具将其转换(一个一个改即太麻烦了)(此外,还有px2rem等插件)
首先,安装。npm install postcss-px-to-viewport –save-dev
其次,在项目的根目录下新建一个postcss.config.js配置文件,并且在配置文件里写入
项目后续可扩展的方向
分类页中的商品应该类似于首页一样,应该有对应类别的具体的商品展示,并且能够添加商品到购物车中。
个人页应该可以写一个用户管理系统,管理用户账号、密码信息,及其财产信息和其他购物信息等。
项目心得
Git代码管理
Vue CLI脚手架+区分代码分类,进行目录结构合理管理
封装思想去设计使用组件:将第三方的东西额外封装,当这个第三方文件不可使用时,我们可以直接修改这个封装文件,保证导出的接口和之前的一样,这样就不会影响我们项目之前使用的情况,鲁棒性高
理解原理的基础上,才能由Bug的现象回溯到代码上,从而debug