从零开始,搭建一个简单的购物平台(十三)前端商城部分
本文最后更新于:9 个月前
从零开始,搭建一个简单的购物平台(十二)前端商城部分 :
https://blog.csdn.net/time_____/article/details/108471436
项目源码(持续更新):https://gitee.com/DieHunter/myCode/tree/master/shopping
这篇文章我们来实现一下前端商城的工具类,其他配置和全局状态
工具类:
工具类我们统一放在utils文件夹下,并部署在Vue原型上(与Axios的一样)
首先我们要实现两个对象深复制的方法,之前博客也有介绍到,后续对全局静态变量做操作时,只能将其定义为只读,也就是不能改变他的值,所以深复制是很有必要的,对于简单的数据用json方式即可,遇上含有function,set,get等属性时需要用到递归版。
JSON:*
export default class Clone { static shallowClone(org) { return JSON.parse(JSON.stringify(org)); } }
递归:
export default class Clone {
static deepClone(org, tag) {
var tag = tag || {};
var name = Object.getOwnPropertyNames(org);
for (var i = 0; i < name.length; i++) {
var desc = Object.getOwnPropertyDescriptor(org, name[i]);
if (typeof desc.value === "object" && desc.value !== null) {
var obj = desc.value.toString() === "[object Object]" ? {} : [];
Object.defineProperty(tag, name[i], {
configurable: desc.configurable,
enumerable: desc.enumerable,
writable: desc.writable,
value: obj
});
Clone.deepClone(desc.value, obj);
} else {
Object.defineProperty(tag, name[i], desc);
}
}
return tag;
}
}
- 本地缓存的封装
import Vue from "vue";
class Storage {
static saveStorage(key, val) {
localStorage.setItem(key, JSON.stringify(val));
}
static getStorage(key) {
try {
return JSON.parse(localStorage.getItem(key)) || [];
} catch (error) {}
}
static clearStorage(key) {
try {
localStorage.removeItem(key);
} catch (error) {}
}
}
Vue.prototype.$storage = Storage;
其他配置:
Events:对全局事件做一个封装,这里针对每一个组件和每一个自定义事件用了一个简单的工厂模式, 降低代码的耦合性,解决事件封闭,但是缺点是在每一个组件销毁时需要作事件取消监听(销毁),否则会导致之前的监听事件执行两次,虽然每个子工厂生产出来的都是独特的产品,但是会导致性能降低,所以要做事件销毁处理
import Vue from "vue"; class Events extends Vue {//继承Vue的自定义事件,使其直接调用 constructor() { super(); } static getInstance() {//返回当前实例的单例 if (!Events._instance) { Object.defineProperty(Events, "_instance", { value: new Events() }); } return Events._instance; } onEvent(_event, _fn) { this.$on(_event, _fn); } onceEvent(_event, _fn) { this.$once(_event, _fn); } emitEvent(_event, _data) { this.$emit(_event, _data); } offEvent(_event, _fn) { this.$off(_event, _fn) } } Vue.prototype.$events = Events.getInstance()
全国省市县的JSON文件
https://gitee.com/DieHunter/myCode/blob/master/shopping/client/shopclient/src/config/city.js静态Config文件
export default class Config {
static Agreement = "http://"; //协议
static BaseUrl = "127.0.0.1"; //请求ip或域名
static ServerUrl = ""; //多级路径名
static ServerPort = ":1024"; //端口
static Path = "/"; //静态文件目录
static CryptoKey = "tokenkey"; //加密信息关键字
static RequestPath =
Config.Agreement + Config.BaseUrl + Config.ServerPort + Config.Path; //服务端静态目录
static RequestTimeOut = 10 * 1000; //请求超时时间
static GetCodeTime = 60 * 1000; //邮箱验证码重发时间
static ShopMaxCount = [1, 2, 3, 4, 5, 6, 7, 8, 9]; //每件商品可购买数量(选择器配置)
static ServerApi = {
//接口名
token: "user/checkToken", //验证token
user: {
userLogin: "user/userLogin", //用户登录
getMailCode: "user/getMailCode", //获取验证码
updateUser: "user/updateUser", //更新用户
userReg: "user/userReg" //注册(移动端)
},
shop: {
shopList: "shop/shopList" //获取商品列表
},
order: {
orderList: "order/orderList", //获取订单列表
addOrder: "order/addOrder", //新增订单
delOrder: "order/delOrder", //删除订单
updateOrder: "order/updateOrder" //更新订单状态
}
};
static UploadName = {
headPic: "upload/headPic" //图片路径
};
static UploadKey = {
headKey: "headPic" //头像上传关键字
};
static StorageName = {
//本地缓存
Token: "token",
ShopCar: "shopCar", //购物车列表
UserInfo: "userInfo" //用户信息
};
static EventName = {
//自定义事件
SelectKind: "selectKind", //分类选择
ChangeCount: "changeCount", //修改商品数量
ShowPicker: "showPicker", //显示,隐藏Picker
CountShop: "countShop", //购物车商品总价
SelectAllChild: "selectAllChild", //全选子选项
SelectParent: "selectParent", //全选父选项
IsLogin: "isLogin", //登录成功
UploadPic: "uploadPic" //上传图片
};
static DefaultPageConfig = {
//默认分页配置
shopType: "",
picType: "",
keyWord: "",
page: 1,
isactive: true,
pageSize: "",
totalPage: 1,
orderId: "",
sort: "1",
orderState: ""
};
}
- 邮箱类型选择配置
export default class Mail {
static address = [
"@qq.com",
"@gmail.com",
"@yahoo.com",
"@msn.com",
"@hotmail.com",
"@aol.com",
"@ask.com",
"@live.com",
"@0355.net",
"@163.com",
"@163.net",
"@263.net",
"@3721.net",
"@yeah.net",
"@googlemail.com",
"@mail.com"
];
}
- 商品类型
export default class ShopType {
//商品类型,图片类型,订单状态
static shopType = [
{ name: "炒货", val: "0" },
{ name: "果味", val: "1" },
{ name: "蔬菜", val: "2" },
{ name: "点心", val: "3" },
{ name: "粗茶", val: "4" },
{ name: "淡饭", val: "5" }
// { name: "其他", val: "6" },
];
static picType = [
{ name: "单个商品", val: "0" },
{ name: "轮播图", val: "1" },
{ name: "分类", val: "2" },
{ name: "主题", val: "3" },
{ name: "其他", val: "4" }
];
static orderState = [
{ name: "未付款", val: "0" },
{ name: "已付款", val: "1" },
{ name: "未发货", val: "2" },
{ name: "已发货", val: "3" },
{ name: "已完成", val: "4" },
{ name: "已退款", val: "5" }
];
}
全局Store
全局store没有用Vuex,而是用本地缓存做了一个数据存储,在src下新建store文件夹,并新建store.js文件将所有的状态值汇总并暴露,这里我们简单搭建一下购物车,在shopCar中新建数据model层state和命令控制controller层action
store.js
import Vue from 'vue' import ShopCar from "./shopCar/action" Vue.prototype.$store = { ShopCar }
state.js
import Vue from "vue" import Config from "../../config/config" export default class State extends Vue { constructor() { super() } set shopCar(val) {//写数据 this.$storage.saveStorage(Config.StorageName.ShopCar, val) } get shopCar() {//读数据 return this.$storage.getStorage(Config.StorageName.ShopCar) || [] } }
action.js
import State from "./state"
import Vue from "vue"
import Config from "../../config/config"
const {
EventName
} = Config;
export default class Action extends Vue {
constructor() {
super()
this._state = new State()
}
set state(val) {
this._state.shopCar = val
}
get state() {
return this._state.shopCar
}
countShopItem() {//修改商品数量
}
delShopItem() {//删除商品
}
selAllChild() {//全选
}
filterSelect() {//刷新商品列表
}
delSelShop() {//删除选择商品
}
}
引入所有包
import Vue from 'vue'
import App from './App'
import router from './router'
import "./style/main.less"
import 'mint-ui/lib/style.css'
import MintUI from 'mint-ui'
import './utils/axios'
import './utils/cryptoTool'
import './utils/storage'
import "./event/event"
import "./store/store"
Vue.use(MintUI);
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: {
App
},
template: '<App/>'
})
到此为止,前端商城准备工作全部完成,下一篇文章正式开始进入开发
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!