vue|【Vue】仿小米商城系统(一)

【Vue】仿小米商城系统(一)
文章目录

  • 【Vue】仿小米商城系统(一)
    • 前言
    • 项目地址:
    • 一、项目概述
      • 项目介绍
      • 商城页面与组件
      • 技术栈
      • 商城各页面展示
        • 商品首页
        • 产品站
        • 商品详情
        • 登录页面:账号 admin 密码 admin
        • 订单确认
        • 购物车页面
        • 订单支付页面
        • 支付宝支付
        • 微信支付
        • 订单列表
      • 项目源码:
    • 二、项目开发前准备
      • 跨域解决
        • jsonp
        • nginx
      • 项目目录结构
      • Storage封装
      • 接口错误拦截
      • Mock设置
        • 集成Mock API(本地集成Mock.js)

前言 本项目是基于Vue全家桶的仿小米商城系统,系列笔记(已完结)如下
【Vue】仿小米商城系统(一)
【Vue】仿小米商城系统(二)
【Vue】仿小米商城系统(三)
【Vue】仿小米商城系统(四)

项目地址: 点击这里仿小米商城系统mimall开发笔记及源码
这里是小飞侠Pan,立志成为一名优秀的前端程序媛!!!
本篇博客收录于我的github前端笔记仓库中,持续更新中,欢迎star~
https://github.com/mengqiuleo/myNote


一、项目概述 项目介绍
本项目是基于Vue全家桶的仿小米商城系统,商城的流程如下:
  • 登录 -> 产品首页 -> 产品站 -> 产品详情
  • 购物车 -> 订单确认 -> 订单支付 -> 订单列表
? 该项目是对小米商城系统的模仿,实现了从浏览商品到结算商品的整个过程。使用Scss、mixin来对公共样式抽离;对不同页面进行组件复用;商品展示图片使用vue-lazyload实现懒加载;通过vuex实现商品的状态管理,最终实现了登录、浏览商品并加入购物车、结算等功能。
项目源码:Github: 仿小米商城mimall系列学习笔记

商城页面与组件
vue|【Vue】仿小米商城系统(一)
文章图片

技术栈
vue|【Vue】仿小米商城系统(一)
文章图片


商城各页面展示
商品首页 首页各个组件的静态代码实现,并实现了图片懒加载,实现了swiper轮播图。
vue|【Vue】仿小米商城系统(一)
文章图片

产品站 产品站页面吸顶组件、参数组件实现。
vue|【Vue】仿小米商城系统(一)
文章图片

商品详情 商品详情交互接口实现。
vue|【Vue】仿小米商城系统(一)
文章图片

登录页面:账号 admin 密码 admin 登录页面交互和接口完整代码实现。
vue|【Vue】仿小米商城系统(一)
文章图片

订单确认 订单确认页面中部分静态模块实现以及接口功能实现。
vue|【Vue】仿小米商城系统(一)
文章图片

购物车页面 购物车头部组件以及购物车所有功能的动态交互实现。
vue|【Vue】仿小米商城系统(一)
文章图片

订单支付页面 订单结算交互实现,同时包含微信支付和支付宝支付同后台对接。
vue|【Vue】仿小米商城系统(一)
文章图片

支付宝支付 vue|【Vue】仿小米商城系统(一)
文章图片

微信支付 vue|【Vue】仿小米商城系统(一)
文章图片

订单列表 vue|【Vue】仿小米商城系统(一)
文章图片

项目源码:
点击这里 Github: mimall

二、项目开发前准备 跨域解决
jsonp 项目里面使用jsonp,先安装
cnpm i jsonp --save-dev
jsonp不是一个请求,而是一个js脚本。利用了js脚本加载没有限制来进行访问.
在浏览器控制台的XHR中没有,而是在JS中出现(是一个JS脚本)。
在项目中导入,import jsonp from 'jsonp'
然后在mounted中设置,
mounted(){ let url = "https://www.baidu.com"; jsonp(url,() => { }) }


nginx 接口代理 - 通过修改Nginx服务器配置来实现
前端修改,后台不动
在根目录创建配置文件:vue.config.js,在里面配置以下内容:
nodejs服务器遵循的是commonjs规范
设置代理后,
module.exports = { devServer:{ host:'localhost', port:8080, proxy:{ '/api':{ target:'http://mall-pre.xxx.cn', changeOrigin:true, pathRewrite:{ '/api':'' } } } } } // 注意:在target里面需要写上接口代理的目标地址

比如有很多接口:
  • http://mall-pre.xxx/server/a.cn
  • http://mall-pre.xxx/server/b.cn
  • http://mall-pre.xxx/server/c.cn
原理: 因为我们需要使用的接口地址可能很多,不可能挨个去进行拦截。所以,这里可以设置一个虚拟的地址/api,实际上,是没有这个地址的。当拦截到/api时,就将主机的点设置为原点(changeOrigin:true),然后添加路径的转发规则,将/api 置为空,转发时就没有/api了

项目目录结构
  • api: 对api的一些处理
  • util:对公共的方法的定义、封装
  • store:使用Vuex的目录
  • pages:项目页面文件
  • storage:数据储存相关
  • assets:小图片、样式文件等
  • components:组件
  • router.js:路由
vue|【Vue】仿小米商城系统(一)
文章图片

需要注意的是:axios是一个库,并不是vue中的第三方插件,所以使用时需要在每个页面进行导入操作,这样就很麻烦。我们可以使vue-axios将axios的作用域对象挂载到vue实例中,这样就可以在需要使用的时候用this来调用。
Vue.use(VueAxios, axios)


Storage封装
  • storage本身虽然有API,但是只是简单的key/value形式,
  • storage只能存储字符串,需要手工转化为json对象,
  • 并且storage只能一次性的清空,不能进行单个的清空,
  • 我们要向storage中存储一些更复杂的数据形式,所有我们需要对storage进行封装。
这里封装的是sessionStorage,实际上就是可以在sessionStorage存储JSON对象,并且可以对这些对象进行一些操作:
setItem(); getItem(); getStorage(); //获取所有数据 clear();

/** * Storage封装 */ const STORAGE_KEY = 'mall'; export default{ //存储值 setItem(key,value,module_name){ if(module_name){ let val = this.getItem(module_name); val[key] = value; this.setItem(module_name); }else{ let val = this.getStorage(); val[key] = value; window.sessionStorage.setItem(STORAGE_KEY,JSON.stringify(val)); } }, //获取某一个模块下面的属性 :user下面的username getItem(key,module_name){ if(module_name){ let val = this.getItem(module_name); if(val) return val[key]; } return this.getStorage()[key]; }, getStorage(){ return JSON.parse(window.sessionStorage.getItem(STORAGE_KEY) || '{}'); }, clear(key,module_name){ let val = this.getStorage(); if(module_name){ if(!val[module_name]) return; delete val[module_name][key]; }else{ delete val[key]; } window.sessionStorage.setItem(STORAGE_KEY,JSON.stringify(val)); } }


接口错误拦截
  • 统一报错
  • 未登录统一拦截
  • 请求值,返回值统一处理
使用axios的拦截器进行处理
//# 根据前端的跨域方式做调整 axios.defaults.baseURL = '/api'; axios.defaults.timeout = 8000; //超时时间为8秒// # 响应拦截器:接口错误拦截 axios.interceptors.response.use(function(response){ let res = response.data; //拿到真正的数据 let path = location.hash; if(res.status == 0) { return res.data; }else if(res.data =https://www.it610.com/article/= 10){ if(path!='#/index'){ window.location.href = 'https://www.it610.com/#/login'; } return Promise.reject(res); }else{ Message.error(res.msg); return Promise.reject(res); } },(error)=>{ let res = error.response; Message.error(res.data.message); return Promise.reject(res); })


Mock设置
在开发阶段,我们可能还不能拿到API文档,所以可以使用Mock模拟数据来进行数据的交互操作。Mock有以下特点:
  • 开发阶段,为了提高效率,需要提前Mock
  • 减少代码冗余,灵活插拔
  • 较少沟通,减少接口联调时间
使用mock的方法有很多:
  • 本地创建json:在本地创建json文件,然后进行调用
  • easy-mock平台:将baseURL设置为easy-mock的接口地址,调用时和正常调用一样
  • 集成Mock API(本地集成Mock.js)
不管哪一种方法,都是要自己写mock数据。
其实Mock.js 很像 json-server。只不过是一个用在单页面,一个用在vue项目中。
在这个项目里并没有进行Mock.js设置,因为这里的后台完全都有接口数据。

集成Mock API(本地集成Mock.js)
cnpm i mockjs --save-dev

在src中建Mock的API:src/mock/api.js
import Mock from 'mockjs' Mock.mock('/api/user/login', { "status": 0, "data": { "id": 12, "username": "admin", "email": "admin@51purse.com", "phone": null, "role": 0, "createTime": 1479048325000, "updateTime": 1479048325000 } })

之后在main.js设置一个mock的开关:
const mock = true if(mock){ require('./mock/api') }

import是预编译加载,刚打开就会被加载。而require是执行到那一行才会被加载,在这里如果设置mock=false,用require的话那么就永远不会被加载。
但是如果设置import,即使是false,也会被加载。
【vue|【Vue】仿小米商城系统(一)】Mock.js比较好的一点就是,它可以设置返回的数据是随机的。
"status": 0, "data": { "id" | 10001-11000: 12, //这里设置每次返回的数据是在10001~11000之间,每次不一样 "username": "@cname", //每次生成随机的名字 "email": "admin@51purse.com", "phone": null, "role": 0, "createTime": 1479048325000, "updateTime": 1479048325000 }

    推荐阅读