刚接触小程序的时候,发现不少微信提供的api都是异步的,如路由跳转,设置和读取缓存,还有获取节点信息等微信的api,都是异步的,须要传入回调函数才能得到结果,在咱们正常的前端开发中,这些都不是异步的,当时很奇怪为何是这样的,最近看了微信的一个开发教程以后,总算是明白了。微信小程序开发教程前端
小程序的底层架构是双线程模式,逻辑层和渲染层是分开的两个线程,渲染层指的就是渲染wxml和wxss,逻辑层指的是执行js文件,两个线程分开运行,经过微信客户端进行通讯,调用微信的api的时候其实就是执行js的线程和微信客户端通讯。
下图是微信官方文档里渲染页面的一个流程图git
注意事项:
上述说了,小程序的渲染层和逻辑层是分开的两个线程,执行js逻辑的只有一个线程,因此在js里声明了的函数,只要有调用,就算页面卸载了,最终都会执行,因此要注意的是,一些interval,或者一些注册的其余函数,若是不想在页面离开后继续执行的话,在页面卸载的时候要注销掉。github
先补充一个知识点:在小程序的appjs的onLaunch里,给全局变量wx添加的属性,是全局有效的,能在其余页面中调用,好比:小程序
onLaunch: function () { wx.aaa = '123456'; wx.bbb = function () { console.log('541521') } } onLoad: function () { console.log(wx.aaa); wx.bbb(); }
以前对发布和订阅一直没什么概念,可是多学点东西总没坏处,近期本身花了点时间专门看了一下,大概明白了一点。微信小程序
订阅:订阅就是在某个地方注册一个自定义的事件,供其余地方调用
发布:触发已经订阅的函数api
下面是我写的一个方法,可能会有一些bug,可是目前没有发现,要是有问题的话欢迎交流一下数组
const myEvent = (function() { // 声明方法 var pub, sub, remove; // 订阅缓存记录 var subCache = {}; // 发布缓存记录 var pubCache = {}; // 参数缓存 var paramCache = {}; // 订阅事件 sub = function(key, fn) { if (!subCache[key]) { subCache[key] = []; } // 添加到订阅缓存中 subCache[key].push(fn); // 若是有发布记录,则直接执行函数 if (pubCache[key]) { if (paramCache[key]) { fn.apply(null, paramCache[key]); } else { fn.apply(null); } // 若是把参数和发布缓存清除的话,就是只容许单次执行 // paramCache[key] = []; // pubCache[key] = undefined; } }; pub = function() { var key = Array.prototype.shift.call(arguments); var fns = subCache[key]; var args = Array.prototype.slice.call(arguments, 0); pubCache[key] = true; paramCache[key] = args; if (!fns || fns.length === 0) { return; } // 有订阅记录,则直接执行 for (let fn of fns) { fn.apply(null, args); } }; remove = function(key, fn) { if (subCache[key]) { if (fn) { for(let i = 0, len = subCache[key].length; i < len; i++) { if (fn == subCache[key][i]) { subCache[key].splice(i, 1); break; } } } else { // 把全部的缓存所有清除 subCache[key] = undefined; pubCache[key] = undefined; paramCache[key] = undefined; } } }; return { pub: pub, sub: sub, remove: remove }; })(); module.exports = myEvent;
使用方法以下:
在appjs里引入MyEvent,并挂载在wx对象上缓存
App({ onLaunch: function () { const MyEvent = require('myEvent的路径'); wx.myEvent = MyEvent; } })
在其中页面页面1的onShow里订阅test1事件,发布test2事件微信
onLoad: function(){ wx.myEvent.sub('test1', function () { console.log('test1'); }); }, onShow: function () { wx.myEvent.pub('test2', 'test2' + new Date().getTime()); }
在页面2的onLoad事件里,发布test1事件,订阅test2事件闭包
onLoad: function(options) { wx.myEvent.pub('test1'); wx.myEvent.sub('test2', function(a){ console.log(a); }); }
一. 在页面1的时候,执行了订阅test1事件,发布了test2事件,可是test1没有发布,订阅的事件不会执行,test2事件没有订阅,也不会执行。
二. 从页面1跳转到页面2,发布了test1事件,直接执行以前已经注册好的test1事件,订阅test2事件,由于有test2的发布事件,订阅以后直接执行,结果是打印一次test1,打印一次test2。
三. 从页面2返回到页面1,执行onShow事件,再次发布test2事件,打印一次test2
四. 从页面1到页面2,发布了test1事件,事件test2重复订阅了,订阅了两次,打印一次test1。
五. 从页面2返回页面1,发布test2,由于test2事件订阅了两次,因此打印了两次test2,因此要注意在不须要的地方把事件注销。
在页面2的onUnload事件里把事件test2注销掉,在从页面2回到页面1的时候,事件test2已经注销了,不会再执行。
onUnload: function() { wx.myEvent.remove('test2'); }
原理和用法说明:
原理:
全局只有一个wx对象,将myEvent挂载在wx上,因此全局也只有一个wx.myEvent对象,myEvent里用到了闭包,订阅的函数和参数都有保存在内存里,因此能实现订阅和发布的功能。
目前事件订阅是用的数组存储,可实现同一个事件订阅屡次,若是不须要的话可自行修改为只能订阅一次的方法。
用法:
通常用于跨页面的操做,好比在某个页面订阅某个事件,在另外一份页面执行了某项操做以后,发布该事件,会直接执行订阅的事件,实现页面间的一些数据传递。
还有也可用于异步请求,先订阅某个事件,异步请求数据,请求数据回来以后,再发布。
使用例子
在使用发布和订阅的方法以前,好比新增地址,从列表页面跳转到新增页面,在新增页面新增地址成功以后,将新增的地址放到缓存,接着返回列表页面,使用navigateBack,在列表页面的onShow里检测是否有缓存,有缓存,则从新加载地址列表
使用发布订阅的方法以后,能够在列表页面的onLoad里订阅新增地址的事件,在新增地址页面,新增以后,发布一个新增地址事件,列表页面监听到有新增地址事件,则新增一个地址,瞬间感受高大上了
用别人的源码能够加快开发速度,并且能够学习别人的源码
We UI WeUI 是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信内网页和微信小程序量身设计,令用户的使用感知更加统一。这个是一个样式库,只提供样式。
vant-weapp 这个是一个组件库,里面封装了一些经常使用的组件,是有赞的vant组件库的小程序版本,我的感受用起来仍是挺好用的。
待补充......