技术 | 从零开始,实现你的小程序

从微信发布的小程序这样的应用形态中,才发现渲染Native(React Native,Weex)并不一定是最优的利用Web能力的解放。在这里我们不讨论微信小程序的应用实现,而是从零开始,让你来设计一个小程序的核心架构,该如何实现?通过分析微信小程序,我们大概需要实现哪些?

如图:

通过观察,小程序的渲染与逻辑是分离开的,这一点上,我个人的判断是限制开发者的编写来达到程序体验的提升,既然分离,那么重点肯定就在通信上了,以iOS的角度来分析,UI的落地呈现使用了WKWebView,那么JS的落地就在JavaScriptCore上了,这两个东西是什么,还请自行了解。

链接:

WKWebView:https://developer.apple.com/reference/webkit/wkwebview

JavaScriptCore:https://developer.apple.com/reference/javascriptcore

通信的目的是让在WKWebView中渲染的视图可以和在JavaScriptCore中运行的逻辑可以“绑定”起来,这里重要的是如何定义通信的协议和数据结构,双方并理解数据结构定义的意图,举个简单的例子,当你的视图上绑定了一个名为clickMe的方法字符串,当用户发生自然点击时,你需要做的事情是组织一个类似的数据结构,比如:

[  
    "type":"clickMe",  
    "args": [      
        "wx_component": "native",      
        "event_args": [         
            "target": "xx"
        ]
    ]
]

当你的Native接收到这样的数据结构时,解析它在传递给运行在JavaScriptCore中的某个业务方法来执行即可。这也就是为什么要实现两种bridge,一种是WKWebView与前端的通信,一种是WKWebView与JavaScriptCore的通信。当然除了逻辑之外,你想调用客户端能力的API也需要这样的通信来处理。

既然小程序的应用特点是一个App,那么从App的特征上来看,你需要实现的核心框架是App,Page,Navigate三个类。从App类来看就非常类似AppDelegate,这是一个App的起始,App的状态如从前台切换到后台等,都应该从这里出发并且一个App在小程序的应用生命周期内只允许实例化一次。Page类的特点就非常类似UIViewController,它代表了一个页面的生命周期,以及它的自有逻辑,比如:一个页面的进入,一个页面的退出,都应该在Page类中有所体现。Navigate类的特点非常类似NavigationController,一个栈结构的导航类,一个Page呈现必然在NavigationController的栈顶,当页面要退出时,必然从栈顶移除此Page,这就是小程序的核心框架要实现的事情,说难也不简单。

从小程序的应用角度来看,整个小程序的视图是一种非常类似XML结构的描述,比如:

<view onTap={ clickMe }></view>

但是其实在背后你需要做的是根据XML结构描述来编译成一种DSL,如果你写过React程序,就知道为什么JSX可以在JS中编写,那是因为最终它会变成一个JS的类,比如:

_createClass(View, [{
 key: "render",    
  value: function render() {      
    var onTap = this.props.onTap;      
    return React.createElement(        
        "div",
       { onClick: onTap },        
        "Hello World icepy !!!"
     );
   }
 }]
);

而这个编译的过程就需要你来自行控制了,你可以编译成JSX这样的结构,也可以编译成你的小程序想要的结构。有了这样的结构之后,你的view像渲染成Web的div还是Native的UIView,完全取决于你的自定义DSL的实现,比如view标签,如果你想编译成Web的完全可以在构建阶段编译成类似React的JSX,如果你想渲染成UIView,那么就需要编译Native对应的render engine中的view DSL,其实这个实现也不难,在JS这边只需要构建出来一个描述数据,在render方法中不是类似JSX中的return React.createElement而是Native.createElement,将你的描述对象,比如style,view type通过Native.createElement方法发送给Native即可。

那么在Page逻辑类中,你调用了setData方法来更新视图,该如何做呢?通过bridge将数据发送给WKWebView,wk中的某个方法接收到了之后,启动diff,重新生成vdom,最后来更新视图。如果是Native的组件呢?其实很好解决,重新生成的vdom,在重新createElement时,如果是Native的组件,又继续通信把数据发送给Native,由Native的render engine来重新渲染Native组件。

最后一步,你要实现的是一个完整的IDE,至于方案你可以用Github开源的https://github.com/electron/electron来实现,这个IDE是来做什么的呢?就是小程序的编码,调试,编译,发布等集成环境,这是为什么?因为你编写的视图如:<view></view>,逻辑如:Page({data:{}}),是没法直接运行在浏览器中的,你需要一个完整的运行环境来开发你的小程序,自然而然的IDE的作用就是帮助你解决运行环境的问题。

至此,你的小程序架构就准备完毕了。

你身边如果有朋友对混合领域(跨技术栈)或全栈,编程感悟感兴趣,可以转发给他们看哦,^_^先谢过啦。

原文发布于微信公众号 - 子曰五溪(fed-talk)

原文发表时间:2019-06-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券