前言
新春佳节、一篇推文都没更新、实属懒惰. 这周正式进入搬砖状态, 继续加油ヾ(◍°∇°◍)ノ゙。
若不想看太多废话的话, 建议直接跳转到结尾看总结即可, 本文主要还是个人对问题的产生到解决的简单复盘.
问题来了
最近在接手个新需求, 因还在开发中的功能, 故简单借用了下面的例子来说明.
假设在小程序入口页(假定为index为入口页)存在如下业务流程、思考下如何实现呢?
前置条件:
1、新人弹窗&专属福利弹窗对用户身份信息敏感、故每次页面显示的时候都需要更新最新状态.
2、专属福利弹窗依赖新人弹窗才决定是否要展示
考虑点:
1、判断是否新人依赖接口A&&业务相对独立, 适合放在compA组件内去实现;
2、判断是否有专属福利依赖接口B&业务相对独立, 适合放在compB组件内实现;
根据业务的独立性&为便于简单描述, 分别封装成独立的业务组件, 暂时将新人弹窗组件命名为compA, 专属福利弹窗命名为compB.
接下来我们看看技术实现!
上图对整体的技术实现有了个流程梳理, 接下来可对照流程去看下面的代码.
compA的主要代码如下:
// wxml
<view>我是新人弹窗组件</view>
// js
Component({
pageLifetimes: {
show: function() {
// 这里放请求接口
this.triggerEvent('showB', {showB: true})
},
}
})
index的主要代码如下:
// wxml
<compA bindshowB="showB"></compA>
<compB canSee="{{canSee}}"></compB>
<view bindtap="hideIndex">跳转到其它页面</view>
//js
const app = getApp()
Page({
data: {},
showB: function (e) {
const { detail: {showB } }= e
this.setData({
canSee: showB
})
},
hideIndex: function(){
wx.navigateTo({
url: '/logs/logs' // logs页面是为了模拟从index页面跳转到其它页面、再回来的场景
})
}
})
compB的主要代码如下:
//wxml
<view>我是专属福利弹窗组件</view>
//js
Component({
properties: {
canSee: {
type: Boolean,
value: false,
observer: function(newval, oldval){
if(newval){
// 若需要展示compB, 这里还需要调接口实时获取专属福利组件相关展示信息
console.log('properties-observer', newval)
}
}
}
}
})
重点来了
步骤1: 进入index页面,假定compA向上传递的showB的值是true[这里很关键] 观察console.log控制台输出如下:
步骤2: 点击跳转到其它页面按钮, 然后再点击头部返回键, 观察console.log控制台输出如下:
经对比发现, 当properties属性值没发生变化时, 使用observer属性是没法做到监听的.
差异点: 希望从某一页面返回到当前页面、仍能及时更新compB的状态。
解决方案
将compB的js文件替换成如下内容:
Component({
properties: {
canSee: {
type: Boolean,
value: false,
observer: function(newval, oldval){
if(newval){
// 若需要展示compB, 这里还需要调接口实时获取专属福利组件相关展示信息
console.log('properties-observer', newval)
}
}
}
},
observers: {
'canSee': function(canSee){
if(canSee){
console.log('observers', canSee)
}
}
},
})
重复上面的步骤1,你会发现:
重复上面的步骤2,你更会发现:
至此,你会发现采用observers属性可以实现需求点.
===========================华丽丽的的分割线、来个总结===========================
上面主要演示的是值为基本数据类型时的触发情况,不知道引用类型的表现是否一致呢?
我们接着往下看, 替换index文件如下
// wxml
<compA bindshowB="showB"></compA>
<compB canSee="{{canSee}}" obj="{{obj}}"></compB>
<view bindtap="hideIndex">跳转到其它页面</view>
// js
const app = getApp()
Page({
data: {},
showB: function (e) {
const obj = {
name: "name"
}
this.setData({
obj
})
},
hideIndex: function(){
wx.navigateTo({
url: '/logs/logs' // logs页面是为了模拟从index页面跳转到其它页面、再回来的场景
})
}
})
替换compB的js文件如下:
Component({
properties: {
obj: {
type: Object,
value: null,
observer: function(newval, oldval){
if(newval){
// 若需要展示compB, 这里还需要调接口实时获取专属福利组件相关展示信息
console.log('properties-observer-obj', newval)
}
}
}
},
observers: {
'obj': function(obj){
if(obj){
console.log('observers-obj', obj)
}
}
},
})
重复步骤1、结果如下:
重复步骤2、结果如下:
经过对比你会发现如下结论:
properties-> observer属性跟 observers属性就传入值的数据类型的表现方面, 存在差异 具体差异点如下:
你以为这2个属性只有这个不同么,当然不是,让我们接着往下看看~
扩展
为更简单易懂地描述该知识点,故只替换index跟compB即可, 先来看看死循环 index文件替换如下:
// wxml
<compB canSee="{{canSee}}" ></compB>
<view bindtap="setDemo">演示扩展用</view>
// js
Page({
data: {},
setDemo: function(){
this.setData({
canSee: true,
})
}
})
compB文件替换如下
// wxml
<view>我是专属福利弹窗组件</view>
// js
Component({
properties: {
canSee: {
type: Boolean,
value: false,
observer: function(newval, oldval){
if(newval){
console.log('properties-observer', newval)
}
}
},
},
data: {
age: 20
},
observers: {
'canSee': function(canSee){
if(canSee){
console.log('observers-properties外传属性', canSee)
// 演示数据监听器可以监听setData数据的变化
this.setData({
age: 20
})
// 演示死循环
// this.setData({
// canSee: true
// })
}
},
"age": function(age){
console.log('observers-内部setData属性', age)
}
},
})
你尝试下把上述注释掉的代码打开, 你会发现你的开发者工具卡死不动了~
这也是官网提到的需要特别注意的地方, 详细介绍如下:
同时你会发现:
observers数据监听器支持监听属性或内部数据的变化;
observer是当定义的属性变量的值发生改变才会触发监听;