小程序页面模型与通信机制解析
小程序的基本架构
该应用由一系列界面构成,这些界面需在配置文件中设定。常见应用布局包括主界面,该界面常使用双标签体系,以及多个附属界面。这种组织方式使得界面间的信息交互成为开发过程中的关键环节。
页面通信的基本概念
页面间的联络是指小程序里不同页面之间的信息交换和互动。一个高效的联络方式必须符合两个基本要求:它得能启动目标页面的某个特定功能,同时还要能把必要的信息带给这个功能。
页面通信的分类方式
按照页面层级可分为三种情况:
1. 同级页面通信(如Tab页之间)
2. 父页面向子页面通信
3. 子页面向父页面通信
按照激活时机可分为:
1. 延迟激活:操作完成后,等待返回目标页面时再激活
rush:js;"> // pageA let isInitSelfShow = true;Page({
data: {
helloMsg: 'hello from PageA'
},onShow() {
// 页面初始化也会触发onShow,这种情况可能不需要检查通信
if (isInitSelfShow) return;let newHello = wx.getStorageSync('__data');
if (newHello) {
this.setData({
helloMsg: newHello
});// 清队上次通信数据
wx.clearStorageSync('__data');
}},onHide() {
isInitSelfShow = false;
},goC() {
wx.navigateto({
url: '/pages/c/c'
});
}
});
2. 立即激活:操作完成后立即激活目标方法
rush:js;"> // pageC Page({ doSomething() { wx.setStorageSync('__data','hello from PageC'); } });
通信方式一:利用onShow/onHide方法
这种方法通过页面生命周期函数和数据传递实现通信。需要注意:
通信后要及时清除数据
依赖setData可能导致读写失败
页面初始化时也会触发onShow
rush:js;"> // PageA let isInitSelfShow = true; let app = getApp();Page({
data: {
helloMsg: 'hello from PageA'
},onShow() {
if (isInitSelfShow) return;let newHello = app.$$data.helloMsg;
if (newHello) {
this.setData({
helloMsg: newHello
});// 清队上次通信数据
app.$$data.helloMsg = null;
}},goC() {
wx.navigateto({
url: '/pages/c/c'
});
}
});
通信方式二:内存数据共享
rush:js;"> // PageC let app = getApp();Page({
doSomething() {
app.$$data.helloMsg = 'hello from pageC';
}
});
采用同样的onShow/onHide机制,但废弃setData,改为直接在内存中调整数据。这样做的好处是效率更高、稳定性更好,不过也必须警惕数据被污染的风险。
通信方式三:事件订阅机制
通过实现事件中心,采用订阅发布模式进行通信。关键点包括:
发布事件时激活目标方法
需要防止重复绑定问题
参数通过事件回调传递
通信方式四:数据绑定方案
rush:js;"> /* /plugins/pubsub.js * 一个简单的PubSub */ export default class PubSub { constructor() { this.PubSubcache = { $uid: 0 }; }on(type,handler) {
let cache = this.PubSubcache[type] || (this.PubSubcache[type] = {});handler.$uid = handler.$uid || this.PubSubcache.$uid++;
cache[handler.$uid] = handler;
}emit(type,...param) {
let cache = this.PubSubcache[type],key,tmp;if(!cache) return;
for(key in cache) {
tmp = cache[key];
cache[key].call(this,...param);
}
}off(type,handler) {
let counter = 0,$type,cache = this.PubSubcache[type];if(handler == null) {
if(!cache) return true;
return !!this.PubSubcache[type] && (delete this.PubSubcache[type]);
} else {
!!this.PubSubcache[type] && (delete this.PubSubcache[type][handler.$uid]);
}for($type in cache) {
counter++;
}return !counter && (delete this.PubSubcache[type]);
}
}
依据响应式理念,借助对公共数据目标进行观察达成联络。范例中借助oba开源组件完成数据监视。务必留意避免重复联结状况,推荐运用单例体制负责公共数据的管控。
//pageA let app = getApp();Page({
data: {
helloMsg: 'hello from PageA'
},onLoad() {
app.pubSub.on('hello',(number) => {
this.setData({
helloMsg: 'hello times:' + number
});
});
},goC() {
wx.navigateto({
url: '/pages/c/c'
});
}
});
通信方式五:直接方法调用
这种hack方法通过缓存页面实例实现直接调用:
rush:js;"> //pageC let app = getApp(); let counter = 0;Page({
doSomething() {
app.pubSub.emit('hello',++counter);
},off() {
app.pubSub.off('hello');
}
});
1. 在页面onLoad事件中缓存this(页面实例)
2. 使用页面路径作为缓存键
3. 直接访问目标页面的属性和方法
长处在于作用力强,又无需跟特定事物关联,不过,在调用获取当前页面信息时,或许会有潜在问题。
总结与建议
//pageA import oba from '../../plugin/oba';let app = getApp();
Page({
data: {
helloMsg: 'hello from PageA'
},onLoad() {
oba(app.$$data,(prop,newvalue,oldValue) => {
this.setData({
helloMsg: 'hello times: ' + [prop,oldValue].join('#')
});
});
},goC() {
wx.navigateto({
url: '/pages/c/c'
});
}
});
小程序间的交互存在多种途径,它们各有优劣之处。设计时需依据实际情境来挑选:
简单场景可使用生命周期方法
rush:js;"> //pageC let app = getApp(); let counter = 0;Page({
doSomething() {
app.$$data.helloTimes = ++counter;
}
});
高频通信推荐内存共享或事件机制
复杂交互可考虑直接方法调用
不论使用何种手段,必须留意内存的分配与回收,同时要妥善应对各种意外状况,以此保障数据交互的平稳运行和结果的可信赖度。
版权声明:本文为 “博览广文网” 原创文章,转载请附上原文出处链接及本声明;
工作时间:8:00-18:00
客服电话
0755-88186625
电子邮件
admin@lanyu.com
扫码二维码
获取最新动态