![5dd556d9534f6646275037521febf83a.png](https://i-blog.csdnimg.cn/blog_migrate/a347e448045e55479702be13e93c812d.jpeg)
作者:马倩
转发链接:https://mp.weixin.qq.com/s/LlZB6ZC5NkxnBj-C5iZNnA
Kbone原理解析
官方介绍
“Kbone 是一个致力于微信小程序和 Web 端同构的解决方案。”
Web端框架基本原理
首先我们来看下普通Web端框架,以Vue框架为例,一份Vue模板对应一个组件,在代码构建阶段编译成调用Dom接口的JS函数,执行此JS函数就会创建出组件对应的Dom树,从而渲染到浏览器页面上。
![56132d37bf2d0f4e1342aeef33952f25.png](https://i-blog.csdnimg.cn/blog_migrate/b5db7e44c91f76ddac849ad562cbf991.jpeg)
然而,小程序是双线程的,并没有Dom树的概念,逻辑层和视图层完全分离,逻辑层是一个纯粹的JSCore,开发者可以编写JS脚本,但是无法直接调用Dom/Bom的api, 没有任何浏览器相关的实现。
在小程序中,视图层和逻辑层的交互是通过数据和时间驱动的。
因此,要实现跨端同构,问题是:怎么将web端代码转为小程序代码?
业界常规做法
目前业界流行的第三方跨端框架们,常规做法都是:静态编译兼容。
![40200e6f9cbe88574fd8f2071cd669b3.png](https://i-blog.csdnimg.cn/blog_migrate/04761524ba237a0b23229c909be7d456.jpeg)
原理是把代码语法分析一遍,然后将其中的模板部分翻译成对应的跨端需求的模板(微信小程序、支付宝小程序、H5、APP等)。
静态编译最大的局限性是无法保证转换的完整性,因为Vue模板和WXML模板的语法并不是直接对等的,Vue的特性设计也和小程序的设计无法划等号,这自然就导致了部分Vue特性的丢失。
比如像Vue中的v-html指令、ref获取Dom节点、过滤器等就通通用不了。
除了Vue自身的特性外,一些原本依赖Dom/Bom接口的Vue插件也无法使用,例如Vue-Router。
Kbone的做法
Kbone是通过提供 适配器 的方式来实现同构,即运行时兼容,而非静态编译。
Kbone的适配器核心包含两个部分:
miniprogram-render:仿造Dom/Bom接口,构造仿造Dom树;
miniprogram-element: 监听仿造Dom树变化,渲染到页面,同时监听用户行为,触发事件。
仿造Dom树和浏览器的运行时对比:
仿造Dom树:
利用内置组件和自定义组件的自引用来进行递归,创建组件树。
如图,自定义custom-dom为递归自引用组件:
![48d1c525035a37bfdba92dd979c85c7a.png](https://i-blog.csdnimg.cn/blog_migrate/ed5296e6ec9b05c73345a54fcba86460.jpeg)
递归的终止条件是遇到特定节点、文本节点或者children空节点。
在创建出组件树后,将Dom节点和自定义组件实例进行绑定,以便后续的Dom更新和操作。
![104a5014e626fff5c4f99a1ffaa31577.png](https://i-blog.csdnimg.cn/blog_migrate/f0a1e551f5cf4ccdee471eca34b58725.jpeg)
kbone这里还对节点数进行了优化:
如果一个dom节点对应一个自定义组件的话,就会创建很多自定义组件,这样会很浪费开销,这里做了子树的合并,也就是说3层才创建一个自定义组件,节省开销。
优化前:17个dom=17个自定义组件;优化后:17个dom=4个自定义组件,蓝色那个是单节点,会合并到上面的树;
![32ddbcb71b36ab286a9b81677fc9d000.png](https://i-blog.csdnimg.cn/blog_migrate/fb8b6c1e83e58393438895546c62c856.jpeg)
dom 子数作为自定义组件渲染的层级数是可以通过配置传入,理论上层级越多,使用自定义组件数量越少,性能也就越好。
一颗很大的 Dom 树,一次性 setData 到视图层,可能会超过 setData 的大小限制(1024kB),拆分成多颗子 Dom 树,然后分批的 setData 到视图层,可以节省开销。
事件监听
小程序的事件是视图层到逻辑层的通讯方式,事件绑定在组件上,当被触发时,就会执行逻辑层中对应的事件处理函数。
小程序的捕获冒泡是在视图层view端,因此逻辑层在整个捕获冒泡流程中各个节点接收到的事件不是同一个对象,小程序事件的捕获冒泡和阻止冒泡等操作必须在WXML模板中声明,无法使用接口实现。
![fe6d9a68754943deab76bb9f981b2cab.png](https://i-blog.csdnimg.cn/blog_migrate/82040915ea987828c776d17b04dd7fd4.jpeg)
为了能够让web端和小程序端的事件系统行为一致,kbone除了仿造了一份Dom树外,也把整个事件系统仿造了一份,即在仿造Dom树上进行捕获冒泡。
当自定义组件监听到用户的操作后,就将事件发往仿造Dom树,后续自定义组件监听到的同一个事件的冒泡就直接忽略。
当触发该节点,仿造Dom树接收到事件后,再进行捕获和冒泡,让事件在各个节点触发。
![23be333ddaa13bf6b9a3b0a113973754.png](https://i-blog.csdnimg.cn/blog_migrate/b60ea7f133cdb5e822acc648f96f8d0e.jpeg)
Kbone的优势
- 支持多个前端框架:Vue、React、Preact 等
- 支持更为完整的前端框架特性:Vue 中的 v-html 指令、Vue-router 插件等
- 提供了常用的 dom/bom 接口
- 可以使用小程序本身的特性:live-player 内置组件、分包功能等
- 提供一些 Dom 扩展接口:getComputedStyle 接口等
Kbone实践
脚手架kbone-cli
官方已经提供了kbone-cli可以用来快速开发:
用npm全局安装kbone-cli
![340c2e428c94f88984287a5de01cf5d2.png](https://i-blog.csdnimg.cn/blog_migrate/9fd5dbe36bf5b227c09af6fdea16580a.jpeg)
可以根据自己的技术栈选择不同的开发模板:React/Vue/Omi/Preact
![eed0bbb68fd130ad258f213d29082444.png](https://i-blog.csdnimg.cn/blog_migrate/7d02351bdba31b82af3a30b4dea251c4.jpeg)
然后就可以愉快的进行开发啦~
![5fbb59e6cfd95a046bce6896914762ee.png](https://i-blog.csdnimg.cn/blog_migrate/b7fc5cc73dc7ddb229ff0761530b0bed.jpeg)
生成的demo项目结构如下:
![18df82e399b43ae60f110dfd048bd8e4.png](https://i-blog.csdnimg.cn/blog_migrate/01b763e56fad4a7ab1ed45c0d8498946.jpeg)
demo中包含了多页跳转、vue-router、vuex等的使用示例,以及mp-webpack-plugin的配置示例。
对于多页面的应用,在 Web 端可以直接通过 a 标签或者 location 对象进行跳转,但是在小程序中则行不通。同时 Web 端的页面 url 实现和小程序页面路由也是完全不一样的。
Demo实例对比
![41ed0b16d286abce2b0d0ee8c171ec84.png](https://i-blog.csdnimg.cn/blog_migrate/c976d6c94ce9ac7763f19a2773d208a4.jpeg)
其中,有一部分两端差异的业务逻辑功能,也给出了3种不同的解决方案:
利用vue-improve-loader,在构建时对dom树节点进行删减,在需要提出的节点加上check-reduce属性 利用reduce-loader,将业务中不需要被打包的代码进行去除,使用行内loader和环境变量来判断 使用样式隐藏,即设置不需要显示的节点样式为 display:none
其他问题
在实际开发中,还会碰到一些细节,例如:
- 多页面开发:修改webpack和mp-webpack-plugin配置
- 小程序内置组件:部分用html标签代替,其他用wx-component + behavior标签
- 小程序自定义组件:修改mp-webpack-plugin配置,补充wxCustomComponents字段,将自定义组件放入组件根目录,使用自定义组件
- 自定义app.js和app.wxss:监听app的生命周期,修改webpack配置补充app.js的构建入口,修改插件配置的generate.app字段,补充app.js
- 扩展dom/bom对象和API:使用 window.$$extend追加方法
- 代码优化:用reduce-loader做体积精简,dom树精简用vue-improve-loader
- 区分环境实现不同功能:process.env.isMiniprogram
更新迭代
kbone由于目前在快速发展期,更新迭代非常迅速,以下特性是对比了8月份的版本和11月份版本,可以看出已经解决了近2/3的问题。
![c86a8f19e256c10a2d694987b37f23e4.png](https://i-blog.csdnimg.cn/blog_migrate/1b50147be50332dcc1e06f4d81e5b44b.jpeg)
小程序技术选型
详细了解了kbone之后,我们来分析下小程序技术框架到底应该怎么选?
kbone & 小程序原生
- 已有web版,需要小程序版:kbone
- 跨平台需求(web + 小程序):kbone
- 对性能特别苛刻 or 追求稳定 or 要用最新功能:小程序原生
- 页面节点数量特别多( 1000 节点以上),且对渲染性能要求高:静态模板转义方案(第三方框架:mpvue/taro等)
第三方框架
- MpVue :不推荐再用了,坑越来越多,内部也表示之后不会投入太多维护
- WePY 1.7.x :不推荐再用了:1.7.x 的版本在最初的设计上的缺陷导致遗留了很多比较严重的问题
- WePY 2.0:现在还是 alpha 阶段,内外部有一些小程序在跑,体验和反馈还可以。但依然 issue 比较多。害怕踩坑的也不推荐使用
- Taro: 也还是有不少问题,但相对来说应该是比 mpVue 和 WePY 更稳定一点
- Uni-app:mpvue的衍生版,跨端 (官方示例有6段) 支持的很好,在H5端实现了一套微信模拟器,可以尝试,是目前唯一支持app端的商用方案,有独立的编辑器HBuildX
- Chameleon: 统一的多态协议,渐进式跨端,提供脚手架命令工具,规划比较宏大
- Omi :基于Taro完成的框架,kbone有支持omi的模板
- Nanachi: 基于react的编译期间的转义框架
总结
没有跨端需求,只需要微信小程序 ==> 小程序原生
web端转小程序 or 两端 or 想要尝鲜 ==> kbone
多端 or Vue 技术栈 ==> uni-app
多端 or React 技术栈 ==> taro
不介意学习新技术了 ==> wepy 2.0 or chaemeleon
写在最后
小程序在非常快速的更新迭代,就算是原生框架也还是有一些坑的,因此没有哪种框架是百分之百完美,需要根据业务具体需求以及自身技术栈偏好来进行选择。
如果是你,你会怎么选择?欢迎你在留言区给出答案。
推荐Vue学习资料文章:
《为什么我不再用Vue,改用React?》
《让Jenkins自动部署你的Vue项目「实践」》
《20个免费的设计资源 UI套件背景图标CSS框架》
《Deno将停止使用TypeScript,并公布五项具体理由》
《前端骨架屏都是如何生成的》
《Vue原来可以这样写开发效率杠杠的》
《用vue简单写一个音乐播放组件「附源码」》
《为什么Vue3.0不再使用defineProperty实现数据监听?》
《「干货」学会这些Vue小技巧,可以早点下班和女神约会》
《探索 Vue-Multiselect》
《细品30张脑图带你从零开始学Vue》
《Vue后台项目中遇到的技术难点以及解决方案》
《手把手教你Electron + Vue实战教程(五)》
《手把手教你Electron + Vue实战教程(四)》
《手把手教你Electron + Vue实战教程(三)》
《手把手教你Electron + Vue实战教程(二)》
《手把手教你Electron + Vue实战教程(一)》
《收集22种开源Vue模板和主题框架「干货」》
《如何写出优秀后台管理系统?11个经典模版拿去不谢「干货」》
《手把手教你实现一个Vue自定义指令懒加载》
《基于 Vue 和高德地图实现地图组件「实践」》
《一个由 Vue 作者尤雨溪开发的 web 开发工具—vite》
《是什么让我爱上了Vue.js》
《1.1万字深入细品Vue3.0源码响应式系统笔记「上」》
《1.1万字深入细品Vue3.0源码响应式系统笔记「下」》
《「实践」Vue 数据更新7 种情况汇总及延伸解决总结》
《尤大大细说Vue3 的诞生之路「译」》
《提高10倍打包速度工具Snowpack 2.0正式发布,再也不需要打包器》
《大厂Code Review总结Vue开发规范经验「值得学习」》
《Vue3 插件开发详解尝鲜版「值得收藏」》
《带你五步学会Vue SSR》
《记一次Vue3.0技术干货分享会》
《Vue 3.x 如何有惊无险地快速入门「进阶篇」》
《「干货」微信支付前后端流程整理(Vue+Node)》
《带你了解 vue-next(Vue 3.0)之 炉火纯青「实践」》
《「干货」Vue+高德地图实现页面点击绘制多边形及多边形切割拆分》
《「干货」Vue+Element前端导入导出Excel》
《「实践」Deno bytes 模块全解析》
《细品pdf.js实践解决含水印、电子签章问题「Vue篇」》
《基于vue + element的后台管理系统解决方案》
《Vue仿蘑菇街商城项目(vue+koa+mongodb)》
《基于 electron-vue 开发的音乐播放器「实践」》
《「实践」Vue项目中标配编辑器插件Vue-Quill-Editor》
《基于 Vue 技术栈的微前端方案实践》
《消息队列助你成为高薪 Node.js 工程师》
《Node.js 中的 stream 模块详解》
《「干货」Deno TCP Echo Server 是怎么运行的?》
《「干货」了不起的 Deno 实战教程》
《「干货」通俗易懂的Deno 入门教程》
《Deno 正式发布,彻底弄明白和 node 的区别》
《「实践」基于Apify+node+react/vue搭建一个有点意思的爬虫平台》
《「实践」深入对比 Vue 3.0 Composition API 和 React Hooks》
《前端网红框架的插件机制全梳理(axios、koa、redux、vuex)》
《深入Vue 必学高阶组件 HOC「进阶篇」》
《深入学习Vue的data、computed、watch来实现最精简响应式系统》
《10个实例小练习,快速入门熟练 Vue3 核心新特性(一)》
《10个实例小练习,快速入门熟练 Vue3 核心新特性(二)》
《教你部署搭建一个Vue-cli4+Webpack移动端框架「实践」》
《2020前端就业Vue框架篇「实践」》
《详解Vue3中 router 带来了哪些变化?》
《Vue项目部署及性能优化指导篇「实践」》
《Vue高性能渲染大数据Tree组件「实践」》
《尤大大细品VuePress搭建技术网站与个人博客「实践」》
《10个Vue开发技巧「实践」》
《是什么导致尤大大选择放弃Webpack?【vite 原理解析】》
《带你了解 vue-next(Vue 3.0)之 小试牛刀【实践】》
《带你了解 vue-next(Vue 3.0)之 初入茅庐【实践】》
《实践Vue 3.0做JSX(TSX)风格的组件开发》
《一篇文章教你并列比较React.js和Vue.js的语法【实践】》
《手拉手带你开启Vue3世界的鬼斧神工【实践】》
《深入浅出通过vue-cli3构建一个SSR应用程序【实践】》
《怎样为你的 Vue.js 单页应用提速》
《聊聊昨晚尤雨溪现场针对Vue3.0 Beta版本新特性知识点汇总》
《【新消息】Vue 3.0 Beta 版本发布,你还学的动么?》
《Vue真是太好了 壹万多字的Vue知识点 超详细!》
《Vue + Koa从零打造一个H5页面可视化编辑器——Quark-h5》
《深入浅出Vue3 跟着尤雨溪学 TypeScript 之 Ref 【实践】》
《手把手教你深入浅出vue-cli3升级vue-cli4的方法》
《Vue 3.0 Beta 和React 开发者分别杠上了》
《手把手教你用vue drag chart 实现一个可以拖动 / 缩放的图表组件》
《Vue3 尝鲜》
《总结Vue组件的通信》
《Vue 开源项目 TOP45》
《2020 年,Vue 受欢迎程度是否会超过 React?》
《尤雨溪:Vue 3.0的设计原则》
《使用vue实现HTML页面生成图片》
《实现全栈收银系统(Node+Vue)(上)》
《实现全栈收银系统(Node+Vue)(下)》
《vue引入原生高德地图》
《Vue合理配置WebSocket并实现群聊》
《多年vue项目实战经验汇总》
《vue之将echart封装为组件》
《基于 Vue 的两层吸顶踩坑总结》
《Vue插件总结【前端开发必备】》
《Vue 开发必须知道的 36 个技巧【近1W字】》
《构建大型 Vue.js 项目的10条建议》
《深入理解vue中的slot与slot-scope》
《手把手教你Vue解析pdf(base64)转图片【实践】》
《使用vue+node搭建前端异常监控系统》
《推荐 8 个漂亮的 vue.js 进度条组件》
《基于Vue实现拖拽升级(九宫格拖拽)》
《手摸手,带你用vue撸后台 系列二(登录权限篇)》
《手摸手,带你用vue撸后台 系列三(实战篇)》
《前端框架用vue还是react?清晰对比两者差异》
《Vue组件间通信几种方式,你用哪种?【实践】》
《浅析 React / Vue 跨端渲染原理与实现》
《10个Vue开发技巧助力成为更好的工程师》
《手把手教你Vue之父子组件间通信实践讲解【props、$ref 、$emit】》
《1W字长文+多图,带你了解vue的双向数据绑定源码实现》
《深入浅出Vue3 的响应式和以前的区别到底在哪里?【实践】》
《干货满满!如何优雅简洁地实现时钟翻牌器(支持JS/Vue/React)》
《基于Vue/VueRouter/Vuex/Axios登录路由和接口级拦截原理与实现》
《手把手教你D3.js 实现数据可视化极速上手到Vue应用》
《吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧【上】》
《吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧【中】》
《吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧【下】》
《Vue3.0权限管理实现流程【实践】》
《后台管理系统,前端Vue根据角色动态设置菜单栏和路由》
作者:马倩
转发链接:https://mp.weixin.qq.com/s/LlZB6ZC5NkxnBj-C5iZNnA