2018 年 10 月13 日,由又拍云和知晓云联合主办的 Open Talk 丨2018 小程序开发者沙龙系列活动广州站拉开帷幕,糗事百科前端负责人宋航在沙龙上做了《更App化的小程序开发》的分享。

“2018 小程序开发者沙龙”是又拍云 Open Talk 继“2018 音视频技术沙龙”后推出的重磅系列活动,与大部分偏重营销、流量的小程序活动不同,本系列活动更热衷于分享小程序开发过程的种种有趣经历和有益的经验。

宋航 / 糗事百科前端负责人

宋航目前负责糗事百科的前端、小程序、小游戏相关的开发工作,对游戏开发、App 开发、Web 前端开发都有深入研究,追求开发好玩的产品。糗事百科在小程序上除了延伸自家产品制作了“糗事百科+ ”小程序外,还在以好玩、有趣为目标的道路上制作更多优质的小程序,比如在涂鸦方面的“填色心语”等。

宋航认为,小程序肩负着强化 Web 能力、简化 App 开发的重大责任,同样是使用 Javascript 开发,很多人把 “Web 页面开发“的一套东西搬到小程序开发上,因此不得其法。在分享中,宋航介绍了借鉴 App 开发来做小程序的思路和方法,内容主要包括:

  • 小程序开发与传统 Web 页面开发的区别;

  • MVC 模式如何帮助优化小程序开发流程;

  • 首屏优化;

  • 硬件能力的授权等。

以下是分享整理:

大家下午好,非常开心能在 Open Talk 的活动上给大家分享糗事百科团队一年多以来的小程序开发经验。我是来自糗事百科的前端开发负责人宋航,今天分享的主题是“更 App 化的小程序开发”。

在小程序发布的一年多以来,糗事百科把自家的 App 产品落地到小程序,而且开发了很多比较好玩的小程序。这些小程序不一定是用户量很高的产品,但是对于大家在小程序开发探索路上会有很大的帮助。

2016 年底微信发布小程序,那个时候功能相对较少。简单的说就是 H5 的“微信化”,在微信里画了一个 H5 框架。但是今天小程序有更多的硬件能力,所以我今天才会分享《更 App 化的小程序开发》的主题。我的看法是不管是目前还是未来,小程序可以替代很多 App。

小程序的意义:加强能力,简化开发

大家认为小程序的出现意味着什么呢?对于开发者来说,我觉得小程序的出现其实“加强了Web的能力,简化了 App 的开发”。

小程序在 Android、iOS 都可以运行,但是它相比于 App 有什么不同?在开发方面,可能早上有一个想法,晚上就可以开发出一个小程序并且实现上线;而开发 App,不可能早上有一个想法,晚上就完成开发并发布到各种各样的应用商店。

小程序与 H5 有什么不一样?小程序比 H5 有更多的能力,兼容性更好。

前端开发者都知道各种浏览器的兼容是一个痛点,小程序的出现首先解决了兼容问题,同样的运行环境可以屏蔽掉不兼容的一些错误,让我们更专心于开发业务逻辑。

第二,小程序有更强的硬件能力。例如把页面上的图片保存到手机相册,普通H5很难做到。

在小程序里面,微信为了防止小程序滥用硬件能力,引入了一个概念——授权,这个概念在 Ap 里面已经有了。为什么小程序要有授权呢?因为“能力越大,责任越大”,微信可以赋予小程序更强的硬件能力,但是为了避免这种能力被乱用,必须加入授权这一概念。如果 H5 能够随便修改相册、修改联系人,那是一种很恐怖的事情。通过微信和授权机制,小程序可以调用到手机的各种硬件能力,相比 H5 有更大的想象空间。比如说我们现在做的直播、录像、拍照的功能都可以用到手机摄像头、麦克风、相册等,甚至可以把文件传到小程序,这个时候,我们产品可以拥有很大的想象空间。

第三,小程序背靠“微信”的用户系统、推送、支付,有利于商业运营,让开发者节省了很多开发工作。H5 没有推送功能,要重新唤回用户需要费很多工夫,比如搞活动等。简单说一下 H5 的主要逻辑,如这张图:


H5 的数据逻辑

H5 的主要逻辑都可以划分为这个流程,通过请求网络数据、处理数据展示到用户面前,用户做出的任何操作,比如点赞、发评论返回到网络,请求回网络之后送回内容。

对比 H5,小程序上有更多的硬件能力,小程序不仅能从网络上获取数据,还可以从硬件设备获取数据。

C:\Users\foryh\Desktop\10月13日Open Talk\宋航\糗事百科宋航_页面_10.jpg

小程序的数据逻辑

MVC:“糗百”开发小程序的业务逻辑

糗事百科团队早期做小程序开发时,由于产品比较广泛,迭代比较快,所以没有采用第三方框架,而是采用了官方的开发文档来工作。

C:\Users\foryh\Desktop\10月13日Open Talk\宋航\糗事百科宋航_页面_11_爱奇艺.jpg

糗事百科早期开发小程序的逻辑

官方的小程序开发文档其实很简单,我们控制对应的 page.js,通过设置 data,渲染到页面即 wxml,让它展示 UI 显示、动画效果和操作反馈。随着开发的深入,我们渐渐发现整个程序变得非常臃肿,因为小程序的逻辑代码都放在了 page.js 里面。一些资料里面提到小程序跟H5有一个很大的区别就是在跳转页面的时候我们不知道怎么传递数据,因为每一个 page.js 都是孤立的。资料里面也会教你如何去传递数据,但是做起来会非常麻烦,每当你创建一个 page.js,你就需要思考这个数据在下一个页面会不会用到,这个数据改了以后上一个页面应该怎么去重新渲染,当页面很多的时候就回变得非常复杂,这样会影响到我们每一次做新页面的开发。

糗事百科团队在重构代码的时候,没有采取第三方框架,在原来基础上把整个 MVC 框架套进去。小程序官方提供的 page.js 可以想象成 MVC 框架下的 Controller ,我们把需要用到的数据抽象成模型,每个模型可以在不同的 page.js 上,通过 page.js 修改 data,最后改到 UI 上。

C:\Users\foryh\Desktop\10月13日Open Talk\宋航\糗事百科宋航_页面_12_爱奇艺.jpg

糗事百科应用MVC后开发小程序的逻辑

我们看下每个步骤负责的内容。原来负责所有逻辑的 page.js 现在只需要负责从 Model 接收数据、响应及管理 View 的生命周期。数据模型做的事情比较简单,处理业务逻辑、提供数据给 page.js、数据持久化。

Model 和 Controller 的数据传输

数据模型和 Controller 是通过怎么样的逻辑进行数据传输的呢?这里运用的是“观察者模型”和“发布/订阅模型”,这两个模型都可以很好地在 Controller 和 Model 之间传递数据。这二者有什么区别呢?

  • 观察者模型(observer)

“观察者模型”可以把 model 的属性,比如文章的点赞功能,是否已经点赞的属性,与 Controller 中的 data 相互绑定,在修改 model 的时候,直接修改 Controller 里面的 data,然后执行 setData 方法,让 UI 上的点赞按钮被点亮。

“点赞”动作的数据传递

在 UI 上我们通过绑定事件,让点赞按钮与 page.js 的逻辑绑定,当点赞事件发生,文章的实例会改变点赞的属性,因为双方是互相绑定的,所以 page.js 里面的 data 也会改变,从而执行 setData 方法。

“观察者模型”比较偏向于单个的属性变化,比如用户登陆,登陆之后有很多属性比如名字、头像、性别都发生改变,如果每一个都用“观察者模型”,每个属性变化都要执行 setData,setData 会用得非常频繁,官方文档是不建议这么频繁去调 setData 方法。所以“观察者模型”比较适用于当数据变化时不会影响到其他改变 UI 数据变化,比如点赞按钮只会影响点赞的 UI 有没有被点亮,不会影响其他数据改变,所以没改变一次,只调用一次 setData 方法,不影响整个程序的性能。要注意的一个地方是“观察者模型”需要绑定,在 Controller 的生命周期里要注意它的解绑和绑定。

  • 发布/订阅模型(Pub-Sub)

“发布/订阅模型”在跨页面传递数据的时候用得比较多,比如前面说的用户登录的例子,用户登录之后可能涉及到几个页面的更新, 如果上个页面也有用户信息的展示也需要更新,如果是大型的软件可能涉及的更新数据会更多。如果按照官方的说法把整个数据 setData 一遍会显得太过繁琐,

“发布/订阅模型”适用于跨越多个页面同时操作 UI 更新,让互相关联的 data,在某个时间点下一起更新,不用频繁的去 setData。比如登陆之后用户头像、性别等进行改变,我们只需要一次setDada 就可以。同样“发布/订阅模型”也要需要绑定,绑定的时候也要注意一下解绑,重复绑定。

登陆模型示意图

上图是登陆模式示意图,通过绑定事件,在 Login Event 发生之后,Pub-Sub 推送到每个 page.js ,多个页面同时更新。

model 管理数据

通过抽象的一个 model,整个程序变得很简单,小程序不仅仅能从网络获取数据,还可以从硬件设备比如说存储空间里面获取数据。前面我们说过把 page.js 里面的 data 抽象成一个 model,每次拿数据会经过上图的三个步骤:首先查内存是否有这个数据,如果没有可以从本地缓存查找,最后我们再从网络/ 硬件设备去查询,这些操作都可以封装会 model 里面,这样调 model 的时候很简单地调一个属性,它底层就已经经过三层查询,这样不仅基于我们的网络请求,还可以很很简单利用小程序提供的缓存空间和文件系统空间

MVC 框架在开发上对我们有很大的帮助,让数据流脱离出 page.js,不用再去考虑各种数据的传递,微信在跳转页面的时候只允许在 URL 上携带一定的字符串,通过这样的方式传递到下一个页面,导致对象类型很难去传递了

小程序的“首屏优化”

如何让小程序更快地展示出内容给用户?这个是在做网页的时候经常遇到的问题,网页加载慢1秒就可能损失大量的用户,做小程序也是如此。

第一步把小程序代码量尽可能压缩资源。很多人刚做小程序的时候,认为可以读本地资源的图片,不用从网络加载,把本地资源的图片塞在小程序里,其实这并不是一个很明智的方法,很多图片可以放到网络上,不一定塞到小程序包里面。

第二步是分包。这有点像做 H5 的时候,把 JS 包划分出来,我们可以把访问频率比较低的页面分到分包里。现在小程序是 4M 的主包加 2M 的分包,我们可以把访问频率很低的页面比如设置页面、用户须知页面,塞到分包,这样整个小程序包变得比较小,主包变小下载速度比较快。

这个时候我们可以很快进入第二阶段,就执行我们的业务逻辑。

C:\Users\foryh\Desktop\10月13日Open Talk\宋航\糗事百科宋航_页面_19_爱奇艺.jpg

小程序的首屏优化

小程序一打开执行的业务逻辑是访问网络,并不一定要等到进到相应的 page.js 才把数据请求出来。每次访问小程序页面的时候,都在读取 model 里面的数据,model 里面数分成 3 层。我们可以把用户上一次退出小程序的状态保存到缓存,等我们再进去的时候就可以看到数据了,并不是每次进去都是一个白屏 loading。

渲染内容要注意的一点是“首次渲染”可以渲染出比较简单的东西,随着页面写得越来越深入,wxml 内的逻辑层级会比较复杂,这时候可以用小程序提供的组件或者模版,把每个部分封装成组件,每个组件渲染的时候内部会进行数据的优化,不会影响整个页面的复杂度,渲染起来比较简单快捷。

善用微信赋予小程序的硬件能力

对于小程序,“能力越大,责任越大”。一个小程序拥有硬件能力时需要注意的是什么呢?微信给与了小程序调用硬件能力的授权,但是我看到很多小程序在授权上都做得很差,比如一进去点了拒绝,找不到重新授权,点了拒绝不会再出现授权了。

小程序在获取一些隐私的东西的时候,比如手机号码、用户信息等,以前做 Web 端可能没有注意到这方面的安全性。微信提供的手机号码是加密的数据,很多人拿到数据后台解密,然后明文传输给前台,这种做法是不理智的,我们在数据传输上要注意加密的信息。

在授权上,使用小程序给我们提供的 Api 接口来授权,一旦拒绝就不会出现提示,现在普遍的做法是使用按钮,按钮来唤醒授权,即使点拒绝了,重新用按钮点击授权还是会弹窗,所以最理想的情况是有一个页面让用户清楚知道自己在哪一方面授了权,这就是我们在拥有了这些能力之后要给用户一个明确的反馈。

善用微信提供的能力,微信提供给我们有很多东西。比如我们之前做一个电商平台,写了半天用户填写信息的框架,后来发现微信已经给我们提供了一个地址选择的功能,包括卡包功能,微信都已经内置在里面。当然微信的 Api 上内容比较多,大家每次开发的时候都需要看一下,我每次看它的开发文档,它拥有的新功能是很多的。

我们在小程序上还能获取到各种各样的网络状态,比如在做一些视频播放类小程序,或者大流量的应用,可以利用这些网络状态来提示用户是否选择打开一些功能。这些都是小程序赋予我们硬件能力之后,我们能够改善小程序用户体验的地方。