重用你的Page(viewController/Activity)
在应用开发的过程中,我们经常遇到一种场景:根据进来的场景不同,页面的点击事件会有不同的业务逻辑。
因为最近在写小程序,就以小程序为例。小程序与iOS的UI架构类似,在小程序中充当UIViewController角色的函数叫做Page。
//A.wxml
<view>A</view>
<button bind:tap="onJump">跳转目标页</button>
//A.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
/**
* 跳转到目标页
*/
onJump() {
wx.navigateTo({
url: '../index/index?source=A',
})
}
})
//B.wxml
<view>B</view>
<button bind:tap="onJump">跳转目标页</button>
//B.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
/**
* 跳转到目标页
*/
onJump() {
wx.navigateTo({
url: '../index/index?source=B',
})
}
})
//index.js
Page({
source: '', //进入页面的来源
data: {
},
/**
* 记录页面来源
*/
onLoad: function (query) {
const {source} = query;
this.source = source;
},
onShow() {
},
/**
* 上传日志
*/
onUpload() {
if (this.source==='A') {
console.log('上传日志到A服务器')
}
if (this.source === 'B') {
console.log('上传日志到B服务器')
}
}
})
代码如上,它实现的需求就是:根据不同的进入来源,将日志上传到不同的服务器。从代码的实现来看,是没有什么问题的。有问题的是:无法不改变代码的情况下进行需求迭代。
比如说过了一段时间,新增需求:有一个页面C,也可以跳转目标,并且在点击上传的时候,将日志上传到C服务器。这个时候就要将index.js进行修改:
/**
* 上传日志
*/
onUpload() {
if (this.source==='A') {
console.log('上传日志到A服务器')
}
if (this.source === 'B') {
console.log('上传日志到B服务器')
}
//新增C的跳转逻辑
if (this.source === 'C') {
console.log('上传日志到C服务器')
}
}
再过一点时间,又有一个新的需求:有一个页面D,也可以跳转目标,并且在点击上传的时候,将日志上传到D服务器.这个时候就要再次修改index.js文件:
/**
* 上传日志
*/
onUpload() {
if (this.source==='A') {
console.log('上传日志到A服务器')
}
if (this.source === 'B') {
console.log('上传日志到B服务器')
}
if (this.source === 'C') {
console.log('上传日志到C服务器')
}
//新增D的跳转逻辑
if (this.source === 'D') {
console.log('上传日志到D服务器')
}
}
随着需求的迭代,我们每次都需要修改index.js文件,然后测试代码的准确性。
这样的做法,带来几个问题:
1.随着来源的页面数量越来越多,onUpload的函数会越来越长,充斥着各种if else,不易阅读,也不易理解。
2.每次修改upload函数,都要重新测试,维护成本高。
既然有这么多的缺点,接下来,我们就使用新的代码编写方式,修复这些缺陷:
第一步,添加indexLogic.js文件
class IndexLogic {
constructor() {
this.uploadLog = null;
}
}
const indexLogic = new IndexLogic();
export default indexLogic;
第二步,改造A.js,B.js文件
// A.js
import indexLogic from '../index/indexLogic.js'
...
...
onJump() {
wx.navigateTo({
url: '../index/index',
})
indexLogic.uploadLog = ()=>{
console.log('上传日志到A服务器')
}
}
// B.js
import indexLogic from '../index/indexLogic.js'
...
...
onJump() {
wx.navigateTo({
url: '../index/index',
})
indexLogic.uploadLog = ()=>{
console.log('上传日志到B服务器')
}
}
第三步,改造index.js文件
//index.js
import indexLogic from './indexLogic.js';
...
...
onUpload() {
if (indexLogic.uploadLog) {
indexLogic.uploadLog()
}
}
三步改造完成之后,上传按钮的事件逻辑,由原来依赖source的情况,变成依赖indexLogic.uploadLog函数,而函数的内容则由传入页确定。以后无论传入C,D,E,F…几百个页面,上传的逻辑都由传入页决定和写入,而不需要修改index.js文件。
非常好,清晰易懂