前言
本文适合对飞书小程序进行过一定开发的读者,目的是提升和优化飞书原生的开发体验。
背景
可能有的读者会疑问,获取页面的实例(this)有什么用。这里简单介绍一下背景。
在开发飞书小程序的时候,业务逻辑可能很复杂,我们想要把很重的代码进行拆分,封装成不同的模块。这样逻辑会更清晰,代码可读性也会更好,并且更易于维护。
这时候,少不了需要在模块里获取页面Page实例,从而进行一些操作。比如最基础的,在模块js文件里对页面的data属性进行读取和改值,即,在模块文件里使用飞书提供的this.setData方法改值、this.data读值。
然而,当你在模块文件里直接写“this”(哪怕是直接写在非箭头函数定义的函数内部),调用都是不成功的,此时的this不会指向当前页面实例。试验一下,我们在模块里输出一个函数,函数里是无法正常调用this.setData或者this.data的,结果打印显示,这两个属性都为undefined。
/* module.js */
export default function test(){
console.log(this.setData) // undefined
console.log(this.data) // undefined
}
那么该如何解决这个问题呢?即我们如何在任何js文件里都能调用this的属性和方法呢?
(伪)方案:将this作为参数传入函数
可以直接把this当作一个参数,参入函数内,再在函数内调用这个参数。这实际上也是调用了页面实例。
/* module.js */
export default function test(_this){
console.log(_this.setData) // 一个function
console.log(_this.data) // data对象
}
/* page.js */
import test from './module'
Page({
call() {
test(_this: this) // 传入this
}
})
用这个方案其实也可以,只是很多函数都不得不带上一个_this参数。对于有强迫症的开发者来说,代码不好看,逻辑意图也不够明朗,不能一下子让没有接触的人看懂你这么写的目的。所以,从精益求精的角度来说,我们可以尝试探索更好的写法。下面来介绍我们的真.方案 :)
方案:获取当前页面实例
我们不妨换个思维,在页面js里调用的this,其实就是获取了当前小程序页面的一个实例对象,指向的就是Page它自身。因此,我们可以不管this,只要想办法从别的途径获取到这个实例对象,即可达到我们的预期目的。
在这里,我们使用一个飞书提供的API —— getCurrentPages。这个方法是用于获取当前页面栈的实例,以数组形式按栈的顺序给出。其中,第一个元素为首页,最后一个元素为当前页面。
大家注意到了,重点是最后一句话。我们调用getCurrentPages方法,获取小程序的页面栈数组,然后获取到数组的最后一个元素,这个元素就是当前页面的实例对象,等同于你在页面js里调用this。
我们把这部分逻辑封装一下,写成一个方法:
/* reactive.js */
const getCurrentPage = () => {
const pages = getCurrentPages()
const last = pages.length - 1
const target = pages[last] // 当前页面实例
return target // 我习惯于把这个实例命名为target
}
这是一个通用方法,你可以单独封装,而不需要写在模块js文件里。然后我们可以在任意模块里使用它,
/* module.js */
import getCurrentPage from './reactive'
export default function test(){
const target = getCurrentPage()
console.log(target.setData) // 等同于使用this.setData
console.log(target.data) // 等同于使用this.data
}
/* page.js */
import test from './module'
Page({
call() {
test() // 无需传入this
}
})
后话
大家看到,这是一个非常简单的逻辑和方案,仅寥寥数句代码即可。但是我认为它带来的收益是可观的,不仅增加了代码可读性和维护性,也便于在此基础上,实现一些飞书原本没有提供的功能和特性。
后续我会写一篇文章,跟大家分享一下,如何利用这个方法去实现飞书小程序组件里的双向绑定(飞书原生的表单组件是单向绑定)
因为开发飞书小程序遇到了不少坑,自己也思索了不少东西,希望借此能够写写文章跟其他人分享一下,同时也是对自己开发过程的一个总结和反思。如果相关的东西最后能集合成一个关于飞书小程序开发的系列,那真是最好不过了。