钟钦成
网名为司徒正美,国内著名的前端专家,对浏览器兼容性问题/选择器引擎/react内部机制等具有深厚的积累,开发有avalon/anu等前端框架,著有《JavaScript框架设计》一书。
这是本系列的最后一篇。小程序封死了操作 DOM 的可能性,并且也不让我们操作视图,所有与视图有关的东西一律接触不了。而它的自定义组件是非常恶心,基本不配叫组件,不能继承叫什么组件。因此我们使用它更早期的动态模板技术 ,template。
我的思路如下,通过编译组件的render方法,将里面的自定义组件变成template类,然后在template类中自己初始化,得到props, state再传给小程序的template标签。换言之,有两套模板。
我们先不管 Dog 组件长得怎么样。
为了让它同时支持小程序与React的render函数,我们需要对render进行改造。将Dog,div等改造成小程序能能认识的类型,如
这个转译是如何实现呢,我们可以通一个插件 syntax-jsx, 它会在visitor遍历出JSX的开标签,闭标签,属性及{}容器。
但 React 无法认识 template 标签,因此还要改造 。
现在看小程序这边小程序无法认识{}, 需要改变成 wx:for 指令。
小程序的 template 有个缺憾,它无法认识 name 这样的属性的,因此我们需要一个东西装着它。那么我们动态创建一个数组吧,改一改 React 那边:
那么小程序的模板则改成这样,去掉各种 template 不认识的东西,加上 wx:for 属性,它对应 React 方的 templatedata 值。然后 template 有一个 data 属性,通过对象解构,完美把所有属性(除方法)传到 dog 的模板中。
然后我们再把 React 的 render 方法改成 React.createElement 形式:
上面的转译工作可以通过 transform-react-jsx babel 插件实现。
class P extends Page这种 es6 定义类的方式,小程序可能也不认识,或者通过 babel 编译后也太复杂。比如说 taro 将 Dog 这个类变成这样:
有长有臭,因此我们最好在 React 中提供一个定义类的方法,叫 miniCreateClass。如此一来我们就能将 Dog 转换得很简洁 。
我们再看Page类。小程序定义页面是通过 Page 工厂实现的,大概是Page(})。小程序在这里的令计很方便我们进行 hack,因为一个Page 类只会有一个实例。
createPage 的实现大既这样:
最后是 React.template 的实现,它负责组装给 template 的数据,这个 template 是小程序的标签。
好了,我的方案就介绍到这里了。如果有人愿意与我一开始搞这东西了,欢迎在 github 找我。
领取专属 10元无门槛券
私享最新 技术干货