您当前的位置: 首页 > 解决方案

在小程序中使用 React with Hooks

  • 作者: admin
  • 发布于 2019-01-15 14:05:17
  • 来源:  
  • 栏目:解决方案

导语: 介绍一下 RemaxRemax 是一个跨多端小程序 React 开发方案,之所以称其为“方案”而非框架是因为这并非一个新的框架,其主要能力就是让 React 能够直接运行在 微

 

介绍一下 Remax

Remax 是一个跨多端小程序 React 开发方案,之所以称其为“方案”而非框架是因为这并非一个新的框架,其主要能力就是让 React 能够直接运行在 微信小程序/支付宝小程序/字节跳动小程序/H5(当然这个本来就支持) 等环境。

可能会有人要会问 “React 不是早就可以运行在小程序中了么“?本文会介绍一下现如今的一些小程序框架的解决方案,以及为什么我们认为把 React 直接搬进小程序是个更为合理的方案。

静态编译类框架

由于大多开发者都更熟悉 React 和 Vue 的 API 和语法,加上小程序本身的开发方式确实让人痛苦,于是便有了一些框架来将这些熟悉的语法编译到小程序的 WXML/WXSS/JS 上,其中比较具有代表性的例如 taro,其目标就是让开发者能够用 React 的开发方式编写小程序。

而这类框架的实现原理其实并非真的是一个 React 或者类 React 框架,而是把看起来像是 JSX 的模板通过静态编译的方式翻译成小程序自身的模板。

这样做的限制非常明显,那就是 JSX 是 JavaScript 的拓展语言(React Blog 写的是 is a syntax extension to JavaScript),而小程序所采用的 WXML 却是一个表达能力非常受限的模板语言,我们不可能完成从一个通用编程语言到模板语言的编译。

而静态编译类框架为了做到这一点,采取的方式就是限制开发者的写法,这也是为什么上面称之为看起来像是 JSX 的模板,这也是为什么 taro 对 JSX 的写法做出了诸多限制。

 

19.jpg

这种方案大多声称这些限制并没有限制生产力,或者符合最佳实践等等。然而我们其实都知道这是由于小程序本身的坑造成的,静态编译方案编译的永远都只会是模板语言,而不是 JSX。

React Hooks

之所以我说这些限制并非基于最佳实践,是因为 React 本身对于 JSX 的定位就 并非模板

JSX is a syntax extension to JavaScript.

在最近 React 团队已经向我们介绍了 Hooks,期望可以 functional component 不仅仅可以是无状态组件,也可以是 useState 的。

import { useState } from 'react';  function Example() {   // Declare a new state variable, which we'll call "count"   const [count, setCount] = useState(0);    return (     <div>       <p>You clicked {count} times</p>       <button onClick={() => setCount(count + 1)}>         Click me       </button>     </div>   ); } 

React 官方博客提到 Classes confuse both people and machines,我们也明显可以看到基于 function 的组件明显更为简洁,噪声更小,未来 React 社区的方向更是会逐渐从 class component 过渡到 functional component。

在这种趋势下,把 JSX 当做模板写,且未来永远也不可能支持 functional component 的方案绝非真的基于最佳实践的选择。

在 Remax 中,我们完全可以使用全新的 Hooks API 来开发组件

因为 Remax 中的 React 就是 React.js,而 JSX 就是 JavaScript 的超集。

上图中使用小程序的原生语法,classname 和 inline style 就只能写成

<view class="weui-navbar__item {{activeIndex == index ? 'weui-bar__item_on' : ''}}"> </view> <view style="left: {{sliderLeft}}px; transform: translateX({{sliderOffset}}px); -webkit-transform: translateX({{sliderOffset}}px);"></view> 

而使用 remax 后就可以写成正常的 react:

const innerStyle = {     left: `${sliderLeft}px`,     transform: `translateX(${sliderOffset}px);`,     '-webkit-transform': `translateX(${sliderOffset}px)`,     width: sliderWidth,   }; const itemClassName = classnames({    'weui-navbar__item': true,     'weui-bar__item_on': activeIndex === index, });  return <View className={itemClassName}>     <View style={innerStyle} />     </View> 

实现原理

核心部分

Remax 的实现原理和基于静态编译的方案有所不同,其核心其实是重新实现了 ReactDOM 的部分。

众所周知,React 本身的设计就是支持跨端渲染的,render 部分和 React 的核心逻辑是解耦的(甚至不在一个 npm 包里)。主要的 render 有 ReactDOM(浏览器),ReactDOMServer(服务器端)和 ReactNative。

Remax 要做的事情和 ReactNative 要做的事情非常类似,我们重新接管了 ReactDOM 的 render。

在原有的 React 页面中,React 在完成 Diff 发现需要修改界面时,又 ReactDOM 把改变 Patch 到页面上。

 

20.jpg

 

而在小程序中由于我们不能直接修改页面,则由 React 完成 DIFF 后由 Remax 把修改 Patch 到内存中的虚拟 DOM 上,然后再通过小程序自己的虚拟 DOM 最后把改变同步到页面上。

 

20.jpg

 

在这里我把这个过程说得非常简单,但实际上是有些坑要填的,主要也都是来自于小程序的限制,后续会有新的文章展开来讲。但是这种实现方式使得我们完全可以把 React 的代码放在小程序的环境中运行。

工程化

工程化很理所当然的用 Webpack 来实现, 除了我们常用的打包等功能外,Webpack 插件也使我们很容易构建一些我们需要的东西出来,例如我们需要在每个 js 入口除了放一个 js 外还需要添加一个 wxml 文件,就可以通过一个很简单的 Webpack 插件来实现。

function GeneraeWxmlWebpackPlugin() {   const content = `<view>...</view>`;   const apply = (compiler) => {     const emit = (compilation, cb) => {       const {         chunks,       } = compilation;       chunks.forEach((item) => {         compilation.assets[`${item.name}.wxml`] = {           source: () => content,           size: () => content.length,         };       });        cb();     };      if (compiler.hooks) {       const plugin = { name: 'GeneraeWxmlWebpackPlugin' };       compiler.hooks.emit.tapAsync(plugin, emit);     } else {       compiler.plugin('emit', emit);     }   };    return {     apply,   }; } 

跨端

这种方案想实现同一套代码跨到 H5 端显然没有什么问题,至于支付宝小程序目前验证了一下可行性也是可行的。

23.gif

 

24.gif

 

项目结构

这个项目主要由几块组成

  • @remax/core
    核心部分,负责 React 组件的 render
  • @remax/cli
    顾名思义,CLI 工具,用于构建生成相应的小程序项目等工作
  • @remax/components
    底层 Component,包括诸如 View 等一些基础组件,用于抹平不同环境的差异
  • @remax/ui
    自带的基础组件库,这部分还待开发,目前只有一两个示例组件

由于目前整个项目才刚刚起步,暂时还不能用于生产环境,目前的几个主要开发者(和打算参与的)有 @CodeFalling @bramblex @ahonn @SimplyY

目前的 DEMO 可以扫码体验:

25.jpg

 

或者在可以按照 github.com/CodeFalling/ 体验本地 DEMO。

如果有人想要参与进来一起开发可以联系我,开发相关的细节文档会陆续更新在 github.com/CodeFalling/ 。

讨论群

 



温馨提示:这篇文章没有解决您的问题?欢迎添加微信:18948083295,有微信小程序专业人员,保证有问必答。转载本站文章请注明转自http://www.okeydown.com/(微信小程序网)。

  • 微信扫描二维码关注官方微信
  • ▲长按图片识别二维码
关注我们

微信小程序官方微信

栏目最新
栏目推荐
返回顶部