前端开发

搭建支持多端商城项目

使用HBuilderX构建支持多端平台编译的移动端商城项目。我们在开发中只需要做少部分的兼容性处理就可以将项目打包成支持各大小程序端、h5端和app端的项目。

项目配置文件

在项目目录下的utils目录中创建config.js,并编写如下内容:

// 公共模块
let  baseUrl = null;  //域名
if(process.env.NODE_ENV == "development"){
	baseUrl = "http://localhost:3000";// 开发版本api地址
}else{
	baseUrl = "https://uapi.xqb.ink";// 生产版本api地址
}
export default baseUrl;

数据请求网络层

为了更好的管理项目中的业务数据请求,我们针对小程序端、h5端和app端做了请求层的封装,尽可能的提高请求代码的复用性,考虑到业务数据之间层层嵌套关系,通过promise封装请求方法解决回调地域问题,通过前段配置代理或后端允许跨域技术解决项目在h5端跨域的问题,通过平台检测技术动态控制测试和线上接口切换问题。

在项目目录下的utils目录中创建http.js,并编写如下内容:

// 封装请求方法
import  baseUrl  from "./config.js"
// 封装
const  http = (options)=>{
	return  new Promise((resolve,reject)=>{
		uni.request({
			url:baseUrl+options.url,
			data:options.data || {},
			method:options.method || "get",
			header:options.header || {
				"content-type":"application/json"
			},
			success:resolve,
			fail:reject
		})
	})
}
export default  http;

封装统一管理接口

在项目目录下的utils目录中创建api.js,并编写如下内容:

// 统一管理接口
// 引入http
import  http  from  "./http.js";
//1. 获取一级分类
const  _getcate = ()=>{
	let options = {
		url:"/api/getcate",
	}
	return http(options)
}
// 2.获取首页轮播图
const  _getBanner = ()=>{
	let options = {
		url:"/api/getbanner"
	}
	return http(options)
}
// 3.获取秒杀活动
const  _getSeckill = ()=>{
	let options = {
		url:"/api/getseckill"
	}
	return http(options)
}
// 4.获取首页数据
const  _getIndexGoods = ()=>{
	let options = {
		url:"/api/getindexgoods"
	}
	return http(options)
}
// 5.获取一级分类下所有的商品
const  _getCateGoodsPage = (data={})=>{
	let options = {
		url:"/api/getcategoodPage",
		data,
	}
	return http(options)
}
// 6.获取所有的商品分类
const  _getCates = ()=>{
	let options = {
		url:"/api/getcates",
	}
	return http(options)
}
// 7.获取制定商品详情信息
const  _getGoodsInfo = (data={})=>{
	let options = {
		url:"/api/getgoodsinfo",
		data,
	}
	return http(options)
}
// 8.获取制定商品详情信息
const  _getPhoneCodeSms = (data={})=>{
	let options = {
		url:"/api/sms",
		data,
	}
	return http(options)
}
// 9.执行登陆操作
const  _wxlogin = (data={})=>{
	let options = {
		url:"/api/wxlogin",
		data,
	}
	return http(options)
}
// 10.检测token是否过期
const  _checkToken = (header={})=>{
	let options = {
		url:"/api/checktoken",
		header,
	}
	return http(options)
}
// 11.插入购物车操作
const  _cartAdd = (data={},header={})=>{
	let options = {
		url:"/api/cartadd",
		data,
		header,
	}
	return http(options)
}
// 12.获取购物车列表
const  _cartList = (data={},header={})=>{
	let options = {
		url:"/api/cartlist",
		data,
		header,
	}
	return http(options)
}
// 13.购物车修改
const  _cartEdit = (data={},header={})=>{
	let options = {
		url:"/api/cartedit",
		data,
		header,
	}
	return http(options)
}
// 14.购物车删除
const  _cartDelete = (data={},header={})=>{
	let options = {
		url:"/api/cartdelete",
		data,
		header,
	}
	return http(options)
}
// 15.订单添加orderadd
const  _orderAdd = (data={},header={})=>{
	let options = {
		url:"/api/orderadd",
		data,
		header,
	}
	return http(options)
}
// 16.查询所有的订单
const  _orderList = (data={},header={})=>{
	let options = {
		url:"/api/orders",
		data,
		header,
	}
	return http(options)
}
export  default {
	_getcate,
	_getBanner,
	_getSeckill,
	_getIndexGoods,
	_getCateGoodsPage,
	_getCates,
	_getGoodsInfo,
	_getPhoneCodeSms,
	_wxlogin,
	_checkToken,
	_cartAdd,
	_cartList,
	_cartEdit,
	_cartDelete,
	_orderAdd,
	_orderList
}

项目主文件

在项目目录的main.js中引入配置文件、接口文件等

//导入vue组件
import Vue from 'vue'
// 导入根组件app
import App from './App'
import  api  from "./utils/api.js"
Vue.prototype.$api = api;
import  baseUrl  from  "./utils/config.js"
Vue.prototype.$baseUrl = baseUrl;
// 取消生产提示
Vue.config.productionTip = false
//指定根组件类型
App.mpType = 'app'
// 实例化vue组件
const app = new Vue({
    ...App
})
// 进行挂载
app.$mount()

组件化构建业务页面

我们整个项目以uniapp框架为基础,而uniapp框架底层基于vue.js开发思想,所以在整个开发中我们还是继续使用vue框架的mvvm模式,以组件化构建我们的业务页面,提高整个项目代码的复用率,同时便于多人协同开发和后期的项目维护升级。

页面结构构建和样式布局

uniapp中界面结构布局兼容了pc端的语法和移动端语法,我们为了保证多端能够更好的兼容适配采用官方的建议,页面结构使用微信小程序的组件构建,样式上采用移动端的flex弹性盒子布局和沿用css大部分的样式语法。

/**
 * 这里是uni-app内置的常用样式变量
 *
 * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
 * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
 *
 */
/* 行为相关颜色 */
$uni-color-primary: #007aff;
$uni-color-success: #4cd964;
$uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
/* 文字基本颜色 */
$uni-text-color:#333;//基本色
$uni-text-color-inverse:#fff;//反色
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
$uni-text-color-placeholder: #808080;
$uni-text-color-disable:#c0c0c0;
/* 背景颜色 */
$uni-bg-color:#ffffff;
$uni-bg-color-grey:#f8f8f8;
$uni-bg-color-hover:#f1f1f1;//点击状态颜色
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
/* 边框颜色 */
$uni-border-color:#c8c7cc;
/* 文字尺寸 */
$uni-font-size-sm:24upx;
$uni-font-size-base:28upx;
$uni-font-size-lg:32upx;
/* 图片尺寸 */
$uni-img-size-sm:40upx;
$uni-img-size-base:52upx;
$uni-img-size-lg:80upx;
/* Border Radius */
$uni-border-radius-sm: 4upx;
$uni-border-radius-base: 6upx;
$uni-border-radius-lg: 12upx;
$uni-border-radius-circle: 50%;
/* 水平间距 */
$uni-spacing-row-sm: 10px;
$uni-spacing-row-base: 20upx;
$uni-spacing-row-lg: 30upx;
/* 垂直间距 */
$uni-spacing-col-sm: 8upx;
$uni-spacing-col-base: 16upx;
$uni-spacing-col-lg: 24upx;
/* 透明度 */
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
/* 文章场景相关 */
$uni-color-title: #2C405A; // 文章标题颜色
$uni-font-size-title:40upx;
$uni-color-subtitle: #555555; // 二级标题颜色
$uni-font-size-subtitle:36upx;
$uni-color-paragraph: #3F536E; // 文章段落颜色
$uni-font-size-paragraph:30upx;

接口交互安全机制

在用户请求业务数据时采用JWT验证方式,验证用户的身份有效性,保证用户私密数据的准确性和安全性。

示例代码:

// 检测是否登陆
let  _checkTokenStatus = async (token=null,_this=null)=>{
	if (!token) {
	
		uni.setTabBarItem({
			index: 2, //位置
			text: "未登录"
		})
		return false;
	}
	// 1.检测是否过期
	let result = await _this.$api._checkToken({
		authorization: token
	})
	if (result.data.code == 403) {
		//失效了。或者token错误
		uni.setTabBarItem({
			index: 2, //位置
			text: "未登录"
		})
		// token失效,清楚缓存
		uni.clearStorage();
		return false;
	} else if (result.data.code == 200) {
		//正常
		uni.setTabBarItem({
			index: 2, //位置
			text: "我的"
		})
		
		return true;
		
	} else {
		// 未知错误
	}
}
export  default  _checkTokenStatus;