不知道有多少小伙伴和之前的我一样,微信小程序的js部分都是用面向过程的方式写的,最后的结果就是代码非常长,其实刚刚写完还好,自己也都清楚哪些部分是做什么的,但是当自己回过头来看时,就发现看的有点吃力了,而且代码非常长,看完所有的代码非常吃力,还有一个就是面向过程的代码中,以访问后台数据为例,我们通常要经常调用wx.request,这个API的复用率是非常高的,同时url每次都得重新写,如果哪天我们更改了url那么岂不是都得要重新改,所以如果全是面向过程的思想写的代码,那么效率是非常低的。
如我之前写的代码:
const app = getApp()
var tt = require('../../utils/util.js');
Page({
/**
* 页面的初始数据
*/
data: {
ordername:"",
time: "",
click:"",
orderimg:[],
orderdetail:"",
orderprice:"",
orderperson:"",
ordernumber:"",
orderwechat:"",
orderid:"",
chatlist:"",
content:"留下点什么吧....",
replyuserid:null,
iv:0,
inputcontent:null,
userimg: "",
username: "",
iscollected:null,
orderlostposition:"",
orderlosttime: "",
sortthings: "",
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
wx.showLoading({
title: '加载中',
mask: 'true'
})
wx.setStorageSync('orderid', options.id)
console.log(options)
var _this=this
var orderimg = _this.data.orderimg
orderimg.push(options.orderimg0)
orderimg.push(options.orderimg1)
orderimg.push(options.orderimg2)
console.log(orderimg)
wx.removeStorage({
key: 'replyuserid',
})
/*wx.setStorage({
key: 'orderid',
data: options.id
})*/
_this.setData({
ordername : options.ordername,
time: options.time,
click: options.click,
/* orderimg0: options. orderimg0,
orderimg1: options.orderimg1,
orderimg2: options.orderimg2,*/
orderdetail: options. orderdetail,
orderprice: options. orderprice,
orderperson: options. orderperson,
ordernumber: options. ordernumber,
orderwechat: options. orderwechat,
orderid: options.id,
orderimg: orderimg,
username: options.username,
userimg: options.userimg,
orderlostposition: options.orderlostposition,
orderlosttime: options.orderlosttime,
sortthings: options.sortthings,
})
wx.request({
url: app.globalData.url+'/est/orderclick.php', // 仅为示例,并非真实的接口地址
data: {
orderid: options.id
},
method: "POST",
header: {
"Content-Type": "application/x-www-form-urlencoded" // 默认值
},
success(res) {
}
})
wx.request({
url: app.globalData.url +'/est/findcollected.php', // 仅为示例,并非真实的接口地址
data: {
orderid: wx.getStorageSync('orderid'),
userid: wx.getStorageSync('userid'),
collectedstatus: 0
},
method: "POST",
header: {
"Content-Type": "application/x-www-form-urlencoded" // 默认值
},
success(res) {
console.log(res.data.collectedstatus)
if (res.data.collectedstatus==1){
_this.setData({
iscollected:true
})
}
else{
_this.setData({
iscollected:false
})
}
}
})
wx.hideLoading()
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
var _this=this
var iv = _this.data.iv
console.log("111")
wx.getStorage({
key: 'userid',
success(res) {
console.log(res.data)
wx.request({
url: app.globalData.url +'/est/userstatus.php', // 仅为示例,并非真实的接口地址
data: {
userid: wx.getStorageSync('userid')
},
method: "POST",
header: {
"Content-Type": "application/x-www-form-urlencoded" // 默认值
},
success(res) {
console.log(res.data)
_this.setData({
iv: res.data.iv
})
iv = res.data.iv
console.log(iv)
wx.hideLoading()
wx.showToast({ title: '加载成功!', duration: 1000 })
},
fail(){
wx.hideLoading()
wx.showToast({ title: '加载失败!', duration:1000 })
}
})
},
fail(res){
console.log(iv)
}
})
var _this = this
wx.request({
url: app.globalData.url +'/est/chatlist.php', // 仅为示例,并非真实的接口地址
data: {
orderid: wx.getStorageSync('orderid')
},
method: "POST",
header: {
"Content-Type": "application/x-www-form-urlencoded" // 默认值
},
success(res) {
console.log(res.data)
_this.setData({
chatlist: res.data
})
}
})
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
formSubmit:function(e){
wx.showLoading({
title: '加载中',
mask: 'true'
})
var _this = this
var useid = wx.getStorageSync('userid')
console.log(useid)
if (e.detail.value.inputchat!=0){
if (useid.length==0){
wx.showToast({
title: '请先登陆!',
duration: 2000,
icon: 'loading'
})
setTimeout(function () {
wx.showModal({
title: '提示',
content: '是否跳转至授权登陆界面?',
success(res) {
if (res.confirm) {
wx.navigateTo({
url: '../user/user/log'
})
} else if (res.cancel) {
}
}
})
}, 1000)
}
else
{
console.log("留言内容")
console.log(e.detail.value.inputchat)
var time = tt.formatTime(new Date())
console.log("时间")
console.log(time)
var userid = wx.getStorageSync('userid')
console.log("测试输出userid")
console.log(userid)
var userinfo = wx.getStorageSync('userInfo')
console.log("userinfo.avatarUrl")
console.log(userinfo.avatarUrl)
var orderid = _this.data.orderid
console.log("orderid")
console.log(orderid)
wx.request({
url: app.globalData.url +'/est/pubchat.php', // 仅为示例,并非真实的接口地址
data: {
userimg: userinfo.avatarUrl,
userid: wx.getStorageSync('userid'),
time: time,
content: e.detail.value.inputchat,
orderid: orderid,
username: userinfo.nickName,
replyuserid: wx.getStorageSync('replyuserid'),
replyopenid: wx.getStorageSync('userid'),
},
method: "POST",
header: {
"Content-Type": "application/x-www-form-urlencoded" // 默认值
},
success(res) {
console.log(res.data)
if (res.data.status == 1) {
wx.showToast({ title: '留言成功!', duration: 500 })
setTimeout(function () {
wx.navigateBack({})
}, 1000)
} else {
wx.showToast({
title: '留言失败,请重试!',
duration: 2000,
icon: 'loading'
})
}
}
})
}
}
else{
wx.showToast({
title: '留言不能为空!',
duration: 500,
icon:'loading'
})
}
},
choicereply:function(e){
var _this=this
console.log(e.currentTarget.dataset.bean.username)
_this.setData({
content: "回复@"+e.currentTarget.dataset.bean.username
})
wx.setStorage({
key: 'replyuserid',
data: e.currentTarget.dataset.bean.username
})
},
imgyu: function (e){
console.log(e)
var that = this,
//获取当前图片的下表
index = e.currentTarget.dataset.index,
//数据源
orderimg= this.data.orderimg;
wx.previewImage({
//当前显示下表
current: orderimg[index],
//数据源
urls: orderimg
})
},
sc:function(e){
var useid = wx.getStorageSync('userid')
if (useid.length == 0) {
wx.showToast({
title: '请先登陆!',
duration: 2000,
icon: 'loading'
})
setTimeout(function () {
wx.showModal({
title: '提示',
content: '是否跳转至授权登陆界面?',
success(res) {
if (res.confirm) {
wx.navigateTo({
url: '../user/user/log'
})
} else if (res.cancel) {
}
}
})
}, 1000)
}
else {
console.log(e)
let iscollected = !this.data.iscollected
this.setData({
iscollected
})
if (iscollected){
wx.request({
url: app.globalData.url +'/est/changecollected.php', // 仅为示例,并非真实的接口地址
data: {
orderid: wx.getStorageSync('orderid'),
userid: wx.getStorageSync('userid'),
collectedstatus:1,
sctime:tt.formatTime(new Date())
},
method: "POST",
header: {
"Content-Type": "application/x-www-form-urlencoded" // 默认值
},
success(res) {
console.log(res.data)
}
})
}else{
wx.request({
url: app.globalData.url +'/est/changecollected.php', // 仅为示例,并非真实的接口地址
data: {
orderid: wx.getStorageSync('orderid'),
userid: wx.getStorageSync('userid'),
collectedstatus: 0,
sctime:tt.formatTime(new Date())
},
method: "POST",
header: {
"Content-Type": "application/x-www-form-urlencoded" // 默认值
},
success(res) {
console.log(res.data)
}
})
}
this.onShow();
console.log(iscollected)
//提示用户
wx.showToast({
title: iscollected ? '收藏成功' : '取消收藏',
icon: 'success',
duration:1000,
})
}
}
})
所以我们在这里模仿后端,用面向对象的编程思想来实现模块化的编码,实现代码的复用和模块分离,提高开发效率。
首先我们先进行逻辑层的划分:
控制器层index.js:代码简单,非常容易读懂,基本上都是对业务逻辑层的调用。
业务逻辑层home-model.js:业务逻辑实现层,业务逻辑通过类方法来封装,继承于模型基类,使用基类的一些公用方法。
基类层Base.js:读取配置层,实现各种公用方法,供逻辑层调用
配置层Config.js:实现URL等等的配置
以下为代码详解(由底层向上):
class Config{
constructor(){
}
}
Config.restUrl = 'http://www.csn.com/tp5/public/index.php/api/v1/'
export{Config}
Config.restUrl 可以理解为定义静态变量
class Config{
constructor(){
}
}
export{Config}
以上为类定义的基本结构,注意要用export来设置“接口”
import{Config} from '../utils/config.js';
class Base {
constructor(){
this.baseRequestUrl=Config.restUrl;
}
request(params){
var url=this.baseRequestUrl+params.url;
if(!params.type){
params.type='GET';
}
wx.request({
url: url,
header:{
'content-type':'application/json',
'token':wx.getStorageSync('token')
},
success:function(res){
params.sCallback && params.sCallback(res.data);
}
})
}
}
export{Base}
我们使用
import{Config} from '../utils/config.js';
来引入类,同时在构造函数中定义变量this.baseRequestUrl=Config.restUrl;
在Base类中,我们定义request业务层公用方法,同时获得从业务层的参数params,在此方法中统一调用wx.request的API
import{Base} from '../../utils/Base.js'
class Home extends Base{
constructor(){
super();
}
getBannerData(id,callback){
var params={
url: 'banner?id='+id,
sCallback:function(res){
callback&&callback(res)
}
}
this.request(params)
}
}
export{Home};
注意,我们要在构造函数中用super();来引入父类
其次在此层中,我们根据业务逻辑定义方法,在方法中定义params,然后将params传入request方法中,也就是基类的方法,这样就可以向服务器请求数据。不再需要重复编写WX.request的API
import { Home } from 'home-model.js';
var home=new Home();
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this._onloadData();
},
_onloadData:function(){
var id=1;
var data = home.getBannerData(id,res=>{
console.log(res)
});
},
})
此层是我们很熟悉的index.js文件,在此文件中,我们只需要引入业务逻辑层文件,然后实例化对象,就可以在index.js中调用业务逻辑层的getBannerData方法,所以此层的代码非常简洁明了。
微信小程序的是异步执行的,所以我们得使用回调函数,具体请看
微信小程序的异步和回调函数
这里补充一点
callback&&callback(res)
这条代码的意思是只有当callBack存在的时候,再执行callBack
通过代码的分层,我们实现了代码功能的模块化,在控制器层的代码非常清楚明了,就是简单的几个方法调用,我们以后再看代码的时候,尽管忘记了细节,但是也能看懂大致的流程,而业务逻辑层更加专注业务方法的实现,
基类提供了各种公用的API,节省了API调用的重复,而配置层,则大大的减少了域名或或环境更改造成的影响。