前言
我们最近一直在做基础服务,都是为了完善技术体系。对于前端来说,我们需要构建一个系统。如果做一个app,也是一个不错的选择,但是一定要分层好:
① 底层框架解决了开发效率问题,将复杂的部分变成了黑盒子,只展示了页面开发的三个固定工具。可以采用固定模式进行开发。
②工程部门为业务开发人员封装一个最小的开发环境,最好是浏览器。如果不可能,请为他们提供类似浏览器的调试环境。
这样业务就可以快速迭代,因为业务开发人员写的代码是相似的,所以底层框架和工程团队(通常是同一个团队)可以在底层解决很多效率和性能问题。
稍微大点的公司,稍微大方的团队也会同时做很多后续的性能监控和错误记录工作,从而形成一套文档->开发->调试->构建->发布->监控分析。完整的技术体系
如果形成了这样的体系,那么甚至内部架构的改变、技术的创新也会基于这个体系。遗憾的是,很多团队只会在这条路径上做一部分,后面会因为各种原因而不会深入。感觉一文不值,而最可怕的行为就是在自己的体系没有形成之前就贸然改变基本框架,所以要小心!
就第三方应用接入而言,微信应该是最好的。百度有直账等类似产品,但系统感仍有待提高。阿里巴巴应该也有类似的技术产品。从我们这个层面来说,知识不多,所以要么操作不好,要么做得不好。
自从小程序诞生以来,我就一直关注着它。至此,整个小程序体系就已经非常完整了。腾讯小程序与腾讯云深度融合。如果使用内测开发者工具,它们都是免费的,并且可以用纯js完成。小程序的前后端不需要服务器、存储、CDN、服务代码。它们都是免费的。后端开发完成后,不需要自己去运维。大杀器的节奏。有时候我想,腾讯的技术实力真是强啊!
小程序结构溯源
小程序的开发文档比较齐全。依然是账户申请->演示流程。一旦熟悉了,就可以完成代码清单和其他过程。前端代码用工具搭建然后上传。后端服务自行维护并配置地址映射。这里我们只关注开发过程并使用其测试帐户。
经过一年多的发展,小程序形成的文档已经比较完整。我们可以从文档和demo中对小程序进行一个粗略的判断:
下面是业务人员可以看到的小程序代码。从这段代码及其运行过程中,我们基本可以猜出小程序的轮廓。我们先来看看它的全局控制器APP:
//应用程序.js
应用程序({
:(){
// 显示本地存储能力
var log = wx.('logs') || []
日志。(Date.now())
wx.('日志', 日志)
// 登录
wx.({
:资源=> {
//发送res.code到后台换取,,
})
// 获取用户信息
wx.({
:资源=> {
if (res.['.']) {
// 已经授权,可以直接调用获取头像昵称,不会弹窗。
wx.({
:资源=> {
// 可以将res发送到后台进行解码
这.. = 资源。
// 由于是网络请求,所以可能会在Page之后返回。
// 所以在这里添加它可以防止出现这种情况
如果(这个.k){
这个.k(res)
})
})
},
:{
: 无效的
})
一个应用只会有一个APP实例,小程序为这个单一实例提供了几个基本的事件定义。我们用的最多的应该是,,(我还没写小程序,所以我猜测):
这里我们追溯一下小程序架构层的执行逻辑,以及如何从APP实例化到视图。这里我们首先澄清几点:
① 其实微信小程序还是提供了执行环境,所以我们还是可以在js环境中访问等属性
② 微信小程序提供的所有展示都是定制化的UI,不用考虑DOM操作。
这里你可以想象一下,小程序界面中有一段真实的代码逻辑,但这除了加载js程序之外什么也没做,所有的页面渲染都是js通过URL通信或者,根据设置的规则调用完成页面渲染。
全局控制器应用程序
这里我们重点关注全局控制器应用程序类的作用。因为我们拿不到源码,只能猜测,加上单步调试。首先,微信容器会准备一个容器,为我们的js代码提供托管环境。容器和构建工具将输出以下页面:
这里他应该已经执行了实例化App的方法:
这段代码在这种环境下显得相当晦涩:
y = () {
e(t) {
var n = 这个;
o(这个,e),
s.((e) {
var o = () {
var n = (t[e] || i.noop).bind(this);
。 =“应用程序”,
。 = e,
(0,
)("应用程序:" + e + " 已");
尝试 {
n.(这个,)
}(t){
.({
:t,
:“在应用程序” + e + “”
})
};
n[e] = o.bind(n)
});
for (t 中的 var r)
!(e) {
克(e) ? (0,
i.warn)("关键字保护", "应用程序的 " + e + " 是 -") : v(e) || ("[ ]" === ...call(t[e]) ? n[ e] = () {
变量n;
。 =“应用程序”,
。 = e;
尝试 {
n = t[e].(这个, )
}(t){
.({
:t,
:“在应用程序” + e + “”
})
n
.bind(n) : n[e] = t[e])
}(r);
这。 && .r(这个。);
var l = () {
"hang" === (.> 0 && void 0 !== [0] ? [0] : {}).mode && (f = !0);
变量 e = (0,
一个。)();
e. && (e[e. - 1].(),
(0,
u.)("", e[e. - 1], !0)),
这。(),
(0,
u.)("")
,h = () {
变量 e = . > 0 && void 0 !== [0] ? [0]:{};
if (0 === e. || "0" === e. ? e. = c : c = e.,
e. = e. || {},
(0,
i.)(e) && (p = !0),
这个。(e),
(0,
u.)(""),
d || e.)
d = !1;
别的 {
变量 t = (0,
一个。)();
t。 && (t[t. - 1].(),
(0,
u.)("", t[t. - 1], !0))
};
如果(“”!= && ){
变量 y = . || {};
y。 = y。 || {},
c = y.,
(0,
i.)(y) && (p = !0),
这个.(y),
(0,
u.)(""),
h.call(这个, y)
} 别的
(0,
i.)("应用程序","找不到");
wx.(l.bind(this)),
wx.(h.bind(this)),
_.call(这个, "" == t.)
关于, [{
钥匙: ””,
: () {
(0,
i.warn)("将被丢弃", "App.是,使用。");
变量 e = (0,
一个。)();
如果(e)
电子页面
}]),
}();
活动将在此处的应用程序中注册。我们在这里注册的是一个事件。这对应于小程序初始化时将执行的回调。所以原则上这个函数应该在安装成功之后执行。这里有一个详细的解释。 H5与H5之间的交互流程(这里是我之前做框架时和同事们达成的交互协议,小程序应该是类似的):
我们通常有一个全局对象来保存所有需要执行函数的对象。比如这里,当执行到某个状态时,就会调用js全局环境中对象上的函数。
因为我们的js注册执行是使用字符串key作为标志,所以执行的时候可能是.app['...']('')
我们将在对象上使用bind来保留相应的作用域环境。此时执行的逻辑是正确的。
小程序中全局没有找到对应的标识。这里猜测是直接在app对象上,APP对象上的方法会直接执行。但是,我在这里有一个问题,如果您想在视图级别注册全局事件该怎么办。这个留着以后再看吧。以下是加载时将执行的对象定义的事件。你可以在下面的代码中看到它:
这将与app.json结合以获取第一个加载页面的信息。默认情况下,采用数组中的第一个。但没有找到获取和设置的具体代码,与主流程无关。我们这里忽略它...然后我们看到代码执行了逻辑。 :
然后它流向在微信容器级别注册事件。我想,无论如何,这应该像微信容器注册事件一样,但我找不到全局密钥。
页面流程
如果有微信小程序的朋友,请在这里给我一些建议,看看你的猜测是否正确。顺便说一句,你可以帮忙解释一下。这也是我认为调用全局键的点。然后,逻辑上,将获取默认视图的类并启动实例。化,这里我们来看看视图级别的代码:
//.js
//获取应用实例
应用程序 = ()
页({
数据: {
:'',
:{},
: ,
: wx.('.open-type.')
},
//事件处理函数
: () {
wx.({
网址:'../日志/日志'
})
},
: () {
如果(应用程序..){
这。({
: 应用程序..,
: 真的
})
} else if (this.data.){
// 由于是网络请求,所以可能会在Page之后返回。
// 所以在这里添加它可以防止出现这种情况
应用程序.k = res => {
这。({
:资源,
: 真的
})
} 别的 {
// 不带 open-type= 的兼容性处理
wx.({
:资源=> {
应用程序..=资源。
这。({
:资源,
: 真的
})
})
},
: (e) {
.log(e)
应用.. = e..
这。({
: e..,
: 真的
})
})
他首先获取当前的应用程序实例:
应用程序 = ()
接下来,视图实例化过程开始。这是Page的类入口。大家要注意,view.js只是一个定义好的类,但是它的实例化应该是在全局控制器中,它的实例化是在这里完成的:
Page实例化后,会自己执行AND,但是这里的AND的区别是看不出来的。
总结
我们这里像盲人一样对微信小程序结构做了一个简单的探索。这里我们发现其实小程序的流程和我们想象的有些不同。这里我们初步认为流程是这样的:
①我们写完小程序的代码后,提交代码
② 在发布过程中,我们的代码经过构建过程,app.json和入口.html(假页面),被重新组装成一个只有js代码的空页面。
③ 加载过程从这里开始。用户点击微信按钮即可进入小程序。
④ 打开微信容器,加载入口页面(我感觉应该有一个规则可以通过URL打开并固定一个小程序页面,以后遇到开发案例再讲)
⑤ 执行环境实例化App,然后自动加载默认Page(这里默认的是)
PS:这里我有一个很疑惑的地方。微信容器的各个事件点什么时候执行、由谁执行?
⑥ 进入页面渲染逻辑
⑦……
这里我也比较关心事件执行后对应的页面是如何更新的,所以这里重点关注这段代码:
;
这。({
: 应用程序..,
: 真的
})
这里出现了一段非常关键的代码:
可以看到,我们已经向微信容器注册了一个异步事件,此时所有的逻辑都交给了它自己。执行完成后,会根据后续找到的回调继续执行。
至于容器如何使用代码找到对应的函数,我没有找到。至此,我们对小程序结构的初步探索就结束了。本周晚些时候我们将继续深入研究这个小程序。
感兴趣的朋友可以关注公众号【先森】并回复关键词“小程序”,获取更多资讯。更多关键词玩法等待你的探索~