上面代码核心干的事其实并不复杂 , 也就是:
- 收集需要用到的生命周期
- 定义setData函数 , 提供给用户层更新UI
- 定义监听函数 , 处理生命周期函数执行
- 通知UI进程开启渲染 。
worker.onmessage = e => {const {type, data} = JSON.parse(e.data);if (type === 'init') {const mountNode = document.createElement('div');document.body.appendChild(mountNode);target = new Vue({el: mountNode,data: () => data,template: template(),created(){worker.postMessage(JSON.stringify({type: 'lifeCircle:create',}),null);}});}}复制代码
可以看到UI线程在初始化的时候 , 一并初始化了 worker层传递来的data , 并对生命周期进行了声明 。当生命周期函数在UI层触发的时候 , 会通知 worker 。在我们的例子中 , create 钩子通过setData 进行了一个更新data的动作 。我们知道 setData 就是拿到数据进行通知更新:// UI线程接收到通知消息 , 更新UI if (type === 'update') {Object.keys(data).map(key => {target[key] = data[key];});}复制代码
说到这里 , 似乎一切都感觉清楚多了 , 我们用worker执行用户js逻辑 , worker内无法操作dom , 无法访问window 。当我们需要更新dom , 可以去通知渲染线程做更新 。我们也很容易想到不断地数据传输对性能的损耗 , 所以我们当然可以做进一步的优化 , 多个setData可以组合一起发送?就是建立一个通信 。其次再看一些 , 我们的worker再通信传输数据的过程中不断通过字符串的parse和stringify文章插图
绿色部分时原生JSON.stringify(), 关于这一块如何提升性能一方面可以通过减少数据传输量 , 其他的优化也可以参考这里如何提升JSON.stringify()的性能
最后你可能会问 , 小程序用法都是 <view>, <text> 之类的标签 , 为啥我这里直接用了 <div> 。其实吧 , 也就是
的语法糖 , 写一个 vue组件 , 组件名称叫view是不是就可以了呢?
这里为大家介绍的也只是小程序的冰山一角 , 内部的容器开放jsBridge能力 , 离线机制 , 跨webview通信机制等等有兴趣的可以去探索 , 当然这里也只是抛砖引玉 。
有兴趣的可以查看源码Vox
结语引用知乎上的一段话:
其实 , 大家对小程序的底层实现都是使用双线程模型 , 大家对外宣称都会说是为了:方便多个页面之间数据共享和交互为native开发者提供更好的编码体验为了性能(防止用户的JS执行卡住UI线程)其他好处但其实真正的原因其实是:“安全”和“管控” , 其他原因都是附加上去的 。因为Web技术是非常开放的 , JavaScript可以做任何事 。但在小程序这个场景下 , 它不会给开发者那么高的权限:不允许开发者把页面跳转到其他在线网页不允许开发者直接访问DOM不允许开发者随意使用window上的某些未知的可能有危险的API , 当然 , 想解决这些问题不一定非要使用双线程模型 , 但双线程模型无疑是最合适的技术方案 。经过上面的介绍 , 是不是发现小程序其实也就那么回事 , 并没有多么....这边文章主要希望能让你对经常使用的框架有一个原理性的初步认识 , 至少我们再用的时候可以规避掉一些坑 , 或者性能问题 。
参考文章:
zhuanlan.zhihu.com/p/81775922
双线程前端框架:Voe.js
作者:muwoo
链接:https://juejin.im/post/5e0d74c96fb9a048401cff8e
来源:掘金
著作权归作者所有 。商业转载请联系作者获得授权 , 非商业转载请注明出处 。
推荐阅读
- 一文讲透数据库事务的四原则
- 黑帽SEO百度第一无压力「仅PC端」
- InnoDB架构,一幅图秒懂
- 梦见小河里有很多小鱼还有一条大鱼 梦见小河里有很多小鱼小虾
- 一根有斑点的香蕉到底有多厉害?
- 警惕!梨 决不能和他们一起吃
- 猪肉不能和10种食物一起吃
- 吃完鸡蛋警惕一件事
- 蚊香液没了可以用什么代替 蚊香液只有一点点了可以继续用吗
- 搓澡巾可以每天用吗 搓澡巾要三个月一换吗