个人介绍:钟钦成,网名为司徒正美,国内著名的前端专家,对浏览器兼容性问题/选择器引擎/react 内部机制等具有深厚的积累,开发有 avalon/anu 等前端框架,著有《Java 框架设计》一书。

众所周知,微信推出小程序以来,可谓火遍大江南北,就像当前互联网兴起时,大家忙着抢域名与开私人博客一样。小程序之所以这么火,是因为微信拥有庞大的用户量,并且腾讯帮你搞定后台问题及众多功能问题(如分享,支付,视频播放,文件上传),相当于你一个人也能做一个公司的事情。在手机上,每个人不可能装超过 100 个以上的 APP,因此这么多小公司想生存下来很不容易,但傍上微信这个大平台,个人也能出一个有上千万人玩的爆款游戏,也能搞一些小商城,避开淘宝京东的锋芒。对于大公司,这也是一个赚钱导流的新途径。相信今后,小程序会越来越火。

但是,小程序对开发人员来说,则不怎么给力。它的 API 非常原始,没有类继承,npm 支持滞后,不能使用 CSS 预处理器。于是市面上出现各种转译框架。转译框架与我们常用的框架不太大一样,转译框架是将我们写的代码翻译成小程序支持的各种文件形式,比如说 wxml, wxss。而转译框架在编写业务时,允许我们使用更为流行的框架形式来写(之所以说形式,因为以 vue 方式写,它实际不是跑一个真正的 vue,以 react 方式写,也不是跑一个真正的 react)。由于小程序不存在 DOM,因此流行那几个框架是无法跑在微信中,但可以用它们的仿造品。

转译框架的最高目标是统一公司的技术栈,让以 react 为技术栈的公司不用再搞 vue,为 vue 为技术栈的公司不用学 react。这在招聘与维护上有很大优势。

目前,市面上的转译框架有 wepy, mpvue, taro。前两者是 vue 风格,使用的是 vue1 的语法,但还是有这么多 vue 语法无法支持。taro 是京东近半年出品的,react 风格,目前还不够稳定,最大的问题是组件不包含组件。

好了,到本文的主角出场。anu 原本是一个迷你 React 框架,对 react16 的兼容程度非常高,能跑 react-router, react-redux, antd, rematch 等等。而 anu 小程序则是在其上面的一个扩展,为它添加了一个 cli 及一个新的 render。cli 用在编译期,将 JSX 转换成 wxml 等,而 miniapp render 用在运行期,让它跑在微信内部。

由于小程序的限制,一切涉及 DOM 的API都不能用,如 findDOMNode, dangerouslySetInnerHTML 及 refs.dom。目前也不支持使用 render props 时,因为 wxml 里面不能运行函数。其他,都可以正常使用,包括

  1. 各种生命周期钩子,页面组件还有 componentDidShow, componentDidHide 两个新钩子
  2. div, h1, span, b 等 html 标签
  3. 用户已经用小程序方式写好的各种组件
  4. 事件里面可以传参,多次 bind this (这是一个重大特殊,其他转译框架做不到)
  5. 多重循环支持
  6. es6, es7 语法糖支持
  7. 组件标签包含组件标签
  8. 无状态组件的支持
  9. onClick 属性自动映射成 bindtap
  10. React.wx 对象拥有原 wx 对象的所有方法,并且对所有请求接口进行 Promise 化
  11. 提供两个通用别名 @components 与 @react,方便用户 import React 与通用组件目录的内容

说了这么多,我们看一下如何使用。

1. 到 https://github.com/RubyLouvre/anu 下载 anu

git clone https://github.com/RubyLouvre/anu.git

2. 进入 anu/packages/cli 目录, 执行 npm link 命令 (如果之前执行过,需要 npm unlink)

3. 回到 anu 目录,这时可以使用 mpreact 创建一个小程序项目

4. 执行 npm start 命令,构建工程

5. 然后使用微信开发工具,打开 下面的 dist 目录

作为一个演示项目。去哪儿网模板包含一些简单的使用演示。大家可以用 vs code 打 。src 目录是源码,dist 目录是最终生成给微信运行的代码。

根据微信小程序的要求,src 主要分为三大块, app.js, pages 目录下的页面组件, components 目录下的通用组件。

阿里云-推广AD

app.js 会 import 所有用到的页面组件的 JS 文件

页面组件的源码与生成代码大概如下

  1. import React from ‘@react’;
  2. import Dog from ‘@components/Dog/index’;
  3. class P extends React.Component {
  4. render() {
  5. return (
  6. <div>
  7. <div>类继承的演示</div>
  8. <Dog age={12} />
  9. </div>
  10. );
  11. }
  12. }
  13. export default P;

会生成两个文件

  1. “use strict”;
  2. Object.defineProperty(exports, “__esModule”, {
  3. value: true
  4. });
  5. var _ReactWX = require(“../../../../ReactWX”);
  6. var _ReactWX2 = _interopRequireDefault(_ReactWX);
  7. var _index = require(“../../../../components/Dog/index”);
  8. var _index2 = _interopRequireDefault(_index);
  9. function _interopRequireDefault(obj) {
  10. return obj && obj.__esModule ? obj : { default: obj };
  11. }
  12. function P() {}
  13. P = _ReactWX2.default.miniCreateClass(
  14. P,
  15. _ReactWX2.default.Component,
  16. {
  17. render: function() {
  18. var h = _ReactWX2.default.;
  19. return h(
  20. “view”,
  21. null,
  22. h(“view”, null, “u7C7Bu7EE7u627Fu7684u6F14u793A”),
  23. h(_ReactWX2.default.template, {
  24. age: 12,
  25. templatedata: “data09558693”,
  26. is: _index2.default
  27. })
  28. );
  29. },
  30. classUid: “c70258”
  31. },
  32. {}
  33. );
  34. Page(_ReactWX2.default.createPage(P, “pages/demo/syntax/extend/index”));
  35. exports.default = P;

wxml

  1. <import src=”../../../../components/Dog/index.wxml” />
  2. <view>
  3. <view>类继承的演示</view>
  4. <template is=”Dog” data=”…data” wx:for=”{{data09558693}}” wx:for-item=”data” wx:for-index=”index” wx:key=”*this”></template>
  5. </view>

我们再来看一下另一个拼多多商城模板。那是使用 sass 做预处理器。

由于用到 https 请求数据,因此需要大家打开右上角进行一个设置

它的全貌如下

从这里两个示例来看,anu 小程序是能 hold 住非常复杂的应用。

如果想了解 anu 小程序的进度或一些注意事项,大家可以访问这里

https://github.com/RubyLouvre/anu/issues/133