|
| 1 | +title: Taro 3.3 alpha 发布:用 ant-design 开发小程序? |
| 2 | +subtitle: Taro 3.3 alpha 发布,支持复用 Web 生态 |
| 3 | +cover: https://img12.360buyimg.com/ling/jfs/t1/184622/15/992/477962/608630a0E139b83d6/f5657eddaef03ba2.png |
| 4 | +categories: Taro |
| 5 | +tags: |
| 6 | + - Taro |
| 7 | + - 小程序 |
| 8 | +author: |
| 9 | + nick: Chen-jj |
| 10 | + github_name: Chen-jj |
| 11 | +date: 2021-04-26 15:15:08 |
| 12 | +--- |
| 13 | + |
| 14 | +小程序的设计并没有完全遵循 Web 规范,导致小程序生态和传统 Web 开发生态之间的割裂,海量优秀的 Web 物料并不能直接用于小程序开发。因而 Taro 在相当一段时间内生态都相对薄弱,UI 框架选择不多的问题更是深深困扰着开发者。 |
| 15 | + |
| 16 | +另一方面,业界有着存量的 H5 应用,中短期内 H5 应用适配到小程序端的需要还会存在。我们希望能减少 H5 应用迁移到小程序端的成本,甚至能够直接运行在小程序端。 |
| 17 | + |
| 18 | +Taro 团队一直在思考如何最大限度地在小程序环境中复用 Web 生态,直到 Taro 3.0 诞生后,这种想法有了落地的可能。下文将介绍基于 Taro 3.0 实现 H5 同构的思路与问题,以及我们尝试适配了三大移动端 UI 框架 **WEUI**、**Ant Design Mobile**、**VantUI** 的实验结果。 |
| 19 | + |
| 20 | +## 一、实现思路 |
| 21 | + |
| 22 | +Taro 3.0 是一款重运行时的跨端框架,它通过模拟实现浏览器的 BOM 和 DOM API 实现了对 React、Vue 等 Web 开发框架的兼容。 |
| 23 | + |
| 24 | +既然已经有了浏览器环境的 BOM 和 DOM API,Taro 应用和 Web 应用之间的鸿沟在于小程序组件和 HTML 标签之间的差异。 |
| 25 | + |
| 26 | +<!--truncate--> |
| 27 | + |
| 28 | +### 支持渲染 H5 标签 |
| 29 | + |
| 30 | +Taro3 的渲染数据流如下: |
| 31 | + |
| 32 | +**前端框架 -> Taro DOM -> 小程序 data** |
| 33 | + |
| 34 | +HTML 标签和小程序组件的标签名、属性、事件是有差异的,而前端框架无需感知这些差异。 |
| 35 | + |
| 36 | +因此前端框架适配层、Taro DOM 层不需要改动,只要在 **Taro DOM 序列化为小程序 data** 这一步作映射即可。 |
| 37 | + |
| 38 | +#### 1. 标签名映射 |
| 39 | + |
| 40 | +HTML 标签相对小程序组件封装程度更低、功能更简单,可以看作是小程序组件的子集。因此可以按一定的规则,把 HTML 标签映射为小程序组件,如: |
| 41 | + |
| 42 | +```js |
| 43 | +// Taro DOM 的序列化数据 |
| 44 | +{ |
| 45 | + nn: 'img' |
| 46 | +} |
| 47 | +// 映射结果 |
| 48 | +{ |
| 49 | + nn: 'image' |
| 50 | +} |
| 51 | +``` |
| 52 | + |
| 53 | +完整的标签名映射规则请看:[RFC 附录一](https://github.com/NervJS/taro-rfcs/blob/html-support/rfcs/0004-rendering-html.md#%E4%B8%80%E6%A0%87%E7%AD%BE%E5%90%8D%E5%BD%B1%E5%B0%84) |
| 54 | + |
| 55 | +#### 2. 属性映射 |
| 56 | + |
| 57 | +如果 HTML 标签的属性能在对应小程序组件的属性上找到对应,则进行映射,如: |
| 58 | + |
| 59 | +```js |
| 60 | +// Taro DOM 的序列化数据 |
| 61 | +{ |
| 62 | + nn: 'a', |
| 63 | + href: 'xxx' |
| 64 | + target: '_blank' |
| 65 | +} |
| 66 | +// 映射结果 |
| 67 | +{ |
| 68 | + nn: 'navigator', |
| 69 | + url: 'xxx', |
| 70 | + openType: 'navigate' |
| 71 | +} |
| 72 | +``` |
| 73 | + |
| 74 | +完整的属性名映射规则请看:[RFC 附录二](https://github.com/NervJS/taro-rfcs/blob/html-support/rfcs/0004-rendering-html.md#%E4%BA%8C%E5%B1%9E%E6%80%A7%E5%90%8D%E5%BD%B1%E5%B0%84) |
| 75 | + |
| 76 | +#### 3. 事件映射 |
| 77 | + |
| 78 | +把 HTML 特有的事件在小程序端找到相似的事件进行映射,如: |
| 79 | + |
| 80 | +| HTML 事件 | 小程序组件事件 | |
| 81 | +| :------- | :----------- | |
| 82 | +| click | tap | |
| 83 | + |
| 84 | +完整的事件映射规则请看:[RFC 附录三](https://github.com/NervJS/taro-rfcs/blob/html-support/rfcs/0004-rendering-html.md#%E4%B8%89%E4%BA%8B%E4%BB%B6%E5%BD%B1%E5%B0%84) |
| 85 | + |
| 86 | +### 样式 |
| 87 | + |
| 88 | +#### 1. 标签选择器 |
| 89 | + |
| 90 | +前文介绍了我们会把 HTML 标签映射为小程序组件,但是 H5 应用中使用到的 CSS 标签选择器就会失效。 |
| 91 | + |
| 92 | +因此 Taro 使用了类名去进行模拟: |
| 93 | + |
| 94 | +1) 为所有 H5 标签都加上类名: `h5-${tagName}`。 |
| 95 | + |
| 96 | +```js |
| 97 | +// 源代码 |
| 98 | +<div /> |
| 99 | +// 渲染结果 |
| 100 | +<view class="h5-div" /> |
| 101 | +``` |
| 102 | + |
| 103 | +2) 使用 postcss 插件处理标签名选择器: |
| 104 | + |
| 105 | +```scss |
| 106 | +// 标签名选择器 |
| 107 | +div {} |
| 108 | +// 经 postcss 插件处理后变为类名选择器 |
| 109 | +.h5-div {} |
| 110 | +``` |
| 111 | + |
| 112 | +#### 2. 浏览器默认样式 |
| 113 | + |
| 114 | +Taro 提供两种内置的浏览器默认样式,可以直接引入生效: |
| 115 | + |
| 116 | +- `@tarojs/taro/html.css`: W3C HTML4 的内置样式。只有 HTML4 标签样式,体积较小,兼容性强,能适应大多数情况。 |
| 117 | +- `@tarojs/taro/html5.css`: Chrome(Blink) HTML5 的内置样式。内置样式丰富,包括了大多数 HTML5 标签,体积较大,不一定支持所有小程序容器。 |
| 118 | + |
| 119 | +### 限制 |
| 120 | + |
| 121 | +理想很美好,但现实却略显骨感。即使 Taro 能实现 BOM、DOM API,支持使用 HTML 标签等,同构方案还是存在着一些框架层面抹平不了的差异。以下列举出若干主要限制: |
| 122 | + |
| 123 | +#### 1. 获取元素尺寸 |
| 124 | + |
| 125 | +在 H5 中我们可以调用 DOM API 同步获取元素的尺寸: |
| 126 | + |
| 127 | +```js |
| 128 | +// h5 |
| 129 | +const el = document.getElementById('#inner') |
| 130 | +const res = el.getBoundingClientRect() |
| 131 | +console.log(res) |
| 132 | +``` |
| 133 | + |
| 134 | +但是在小程序中,获取元素尺寸的 API 是异步的: |
| 135 | + |
| 136 | +```js |
| 137 | +// 小程序 |
| 138 | +const query = Taro.createSelectorQuery() |
| 139 | +query.select('#inner') |
| 140 | + .boundingClientRect() |
| 141 | + .exec(res => { |
| 142 | + console.log(res) |
| 143 | + }) |
| 144 | +``` |
| 145 | + |
| 146 | +因此不能兼容那些使用了同步 DOM API 去获取元素尺寸的组件。 |
| 147 | + |
| 148 | +#### 2. DOM API 差异 |
| 149 | + |
| 150 | +`<canvas>`、`<video>`、`<audio>` 等标签在 H5 端可以直接调用 `HTMLElement` 上的方法: |
| 151 | + |
| 152 | +```js |
| 153 | +// h5 |
| 154 | +const el = document.getElementById('myVideo') |
| 155 | +el.play() |
| 156 | +``` |
| 157 | + |
| 158 | +但是在 Taro 中,要调用组件上的原生方法,必须先创建对应的 `Context`: |
| 159 | + |
| 160 | +```js |
| 161 | +// 小程序 |
| 162 | +const ctx = Taro.createVideoContext('myVideo') |
| 163 | +ctx.play() |
| 164 | +``` |
| 165 | + |
| 166 | +#### 3. 样式限制 |
| 167 | + |
| 168 | +部分样式或 CSS 选择器在小程序中不支持,如: |
| 169 | + |
| 170 | +- 通配符 * |
| 171 | +- 媒体查询 |
| 172 | +- 属性选择器,当属性不是对应小程序组件的内置属性时 |
| 173 | + |
| 174 | +## 二、使用方法 |
| 175 | + |
| 176 | +### 升级 3.3.0-alpha 版本 |
| 177 | + |
| 178 | +首先需要安装 v3.3 的 CLI 工具: |
| 179 | + |
| 180 | +```bash |
| 181 | +npm i -g @tarojs/cli@alpha |
| 182 | +``` |
| 183 | + |
| 184 | +然后进入项目,把 `package.json` 文件中 taro 相关依赖的版本修改为 `^3.3.0-alpha.2`,再重新安装依赖(建议先把 **node_modules** 文件夹删除)。 |
| 185 | + |
| 186 | +### 安装同构插件 |
| 187 | + |
| 188 | +为了节省项目空间,同构功能是可选的,以 Taro 插件的形式提供。 |
| 189 | + |
| 190 | +首先开发者需要安装插件 `@tarojs/plugin-html`: |
| 191 | + |
| 192 | +```bash |
| 193 | +npm i @tarojs/plugin-html |
| 194 | +``` |
| 195 | + |
| 196 | +然后配置使用此插件: |
| 197 | + |
| 198 | +```js |
| 199 | +// config/index.js |
| 200 | +const config = { |
| 201 | + // ... |
| 202 | + plugins: [ |
| 203 | + '@tarojs/plugin-html' |
| 204 | + ] |
| 205 | +} |
| 206 | +``` |
| 207 | + |
| 208 | +## 三、示例项目 |
| 209 | + |
| 210 | +为了验证同构功能的可用性和效果,我们对 CSS 样式库 **WEUI**、React 组件库 **Antd Design Mobile**、Vue2 组件库 **VantUI** 的所有组件进行了测试。 |
| 211 | + |
| 212 | +测试效果比较理想,甚至稍微超出我们的预期,配合各组件库自身的按需加载能力,能以小巧的体积使用丰富的组件,相信各位开发者会喜欢这个功能。 |
| 213 | + |
| 214 | +### WEUI |
| 215 | + |
| 216 | +仓库地址:[taro-weui](https://github.com/NervJS/taro-weui) |
| 217 | + |
| 218 | +WEUI 是一个 CSS 的样式库,与框架无关,兼容性比较高,大部分组件能直接使用。 |
| 219 | + |
| 220 | +### Antd Mobile Design |
| 221 | + |
| 222 | +仓库地址:[taro-antd-mobile](https://github.com/NervJS/taro-antd-mobile) |
| 223 | + |
| 224 | +> Antd Mobile Design 官方已经相当久没有维护,此适配项目属于实验性质。 |
| 225 | +
|
| 226 | +能直接兼容使用的组件大概为 80%,主要问题在于: |
| 227 | + |
| 228 | +1. 组件库里广泛使用了 SVG,目前并不支持。 |
| 229 | +2. 不能使用需要同步获取元素尺寸的部分组件。 |
| 230 | + |
| 231 | +### VantUI |
| 232 | + |
| 233 | +仓库地址:[taro-vant](https://github.com/NervJS/taro-vant) |
| 234 | + |
| 235 | +VantUI 的组件十分丰富,能直接兼容使用的组件大概为 70%。部分开发者会在 Taro 中配合使用 Vant Weapp,但 Vant Weapp 只能运行在微信小程序,因此对 VantUI 的直接适配是一个很好的补充。 |
| 236 | + |
| 237 | +适配过程主要遇到的问题有: |
| 238 | + |
| 239 | +1. 少量组件内置的 SVG ICON 不能显示。 |
| 240 | +2. 不能使用需要同步获取元素尺寸的部分组件。 |
| 241 | +3. Vue `<transition>` 组件需要额外适配。 |
| 242 | + |
| 243 | +## 四、共建倡议 |
| 244 | + |
| 245 | +同构方案还在持续优化中,部分实现还没有最终定稿。欢迎各位开发者到我们的论坛下留言,提出您的宝贵意见~:[同构方案 RFC](https://github.com/NervJS/taro/discussions/9029)。 |
| 246 | + |
| 247 | +另外,上述三款 Web UI 框架很多目前没能兼容的组件,只要针对小程序环境做一点兼容工作,是可以进行使用的。一款框架的生态需要官方和社区共同努力建设,单靠 Taro 团队及300多位贡献者的人力没办法撑起整个社区的生态。我们希望这三个兼容性示例项目能起到抛砖引玉的作用,吸引广大开发者进行共建,一起完善上述组件库,甚至不断地引入更多的 Web 端生态库,让跨端开发变得更轻松。十分期待您的参与~ |
| 248 | + |
| 249 | + |
| 250 | + |
| 251 | + |
0 commit comments