• QQ
  • nahooten@sina.com
  • 常州市九洲新世界花苑15-2

微信开发

在小程序中运用 React with Hooks

原创内容,转载请注明原文网址:http://homeqin.cn/a/wenzhangboke/jishutiandi/weixinkaifa/2019/0506/486.html

 
引见一下 RemaxRemax是一个跨多端小程序 React 开发计划,之所以称其为“计划”而非框架是由于这并非一个新的框架,其主要才能就是让 React 可以直接运转在 微信小程序/支付宝小程序/字节跳动小程序/H5(当然这个本 ...
 
引见一下常州网站开发建设 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 的写法做出了诸多限制。
 
 
 
 
 
这种计划大多宣称这些限制并没有限制消费力,或者契合最佳理论等等。但是我们其实都晓得这是由于小程序自身的坑形成的,静态编译计划编译的永远都只会是模板言语,而不是 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 到页面上。
 
 
 
 
 
 
 
而在小程序中由于我们不能直接修正页面,则由 React 完成 DIFF 后由 Remax 把修正 Patch 到内存中的虚拟 DOM 上,然后再经过小程序本人的虚拟 DOM 最后把改动同步到页面上。
 
 
 
 
 
 
 
在这里我把这个过程说得十分简单,但实践上是有些坑要填的,主要也都是来自于小程序的限制,后续会有新的文章展开来讲。但是这种完成方式使得我们完整能够把 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 端显然没有什么问题,至于支付宝小程序目前考证了一下可行性也是可行的。

上篇:上一篇:微信小程序自定义组件完成 tabBar、navBar
下篇:下一篇:小程序page级禁用页面滚动