Remax One - 重新设计小程序的跨平台开发

858 阅读3分钟

跨平台开发的挑战

小程序作为一项非标准的技术,各个小程序平台之间虽然大体上相似,但依然有非常多的差异。“一次开发多端运行”当然是非常美好的愿望,但我们在设计 Remax 之初就意识到各个小程序平台之间的差异是无法被抹平的,每家小程序平台有太多的私货,更没有一个标准来指导我们该如何抹平这些差异。

所以我们在最开始,为每个小程序平台提供了独立的基础组件。开发者如果要做跨平台开发,需要自己去封装基础组件。但很快,我们也意识到这对开发者来说是一件很麻烦的事情,特别是后面我们要支持更多平台的话。

Remax One

受 CSS 属性名前缀的启发,我们重新设计了 Remax 的跨平台方案。我们非常克制地选取了 9 个基础组件,统一了他们之间非平台私有的属性,并且以属性名前缀的方式来支持各个平台私有的特性。我们希望开发者在做跨平台开发时能清楚地意识到你写下的这行代码只会在特定的平台上生效。

Remax One 就是我们提供的跨平台解决方案。通过 remax/one 提供跨平台的组件。

import * as React from 'react';
import { View, Button } from 'remax/one';

export default () => {
  const [count, setCount] = React.useState(0);

  return (
    <View alipay-onAppear={() => console.log('Aha!')}>
      <View>{count}</View>
      <Button onTap={() => setCount(count + 1)}>+1</Button>
    </View>
  );
};

可以看到,对于 onTap 这样通用的属性我们进行了统一,而支付宝独有的 onAppear 属性,则需要加上 alipay- 的前缀。

完整的示例项目

使用

从模板创建项目:

$ npx degit remaxjs/template-one my-app
$ cd my-app

或者在已有的项目中引入:

// remax.config.js
module.export = {
  // 通过设置 one: true 来开启 Remax One。
  one: true,
  // 通过环境变量区分不同平台的输出目录
  output: 'dist/' + process.env.REMAX_PLATFORM,
};

小程序配置

app.config.js 以及页面的 config.js 配置文件支持多端配置方式:

// app.config.js
const title = '小程序标题';
const bgColor = '#fff';
const pages = ['pages/index/index'];

// 支付宝
exports.alipay = {
  pages,
  window: {
    defaultTitle: title,
    titleBarColor: backgroundColor,
  },
};

// 微信
exports.wechat = {
  pages,
  window: {
    navigationBarTitleText: title,
    navigationBarBackgroundColor: backgroundColor,
  },
};

使用文件名后缀区分不同平台代码

通过创建不同平台的同名文件来封装跨平台组件和 API。例如:

// src/api/showToast/index.js
import { showToast } from 'remax/alipay';

export default showToast;
// src/api/showToast/index.wechat.js
import { showToast } from 'remax/wechat';

export default options => {
  showToast({
    ...options,
    title: options.content,
  });
};
// src/pages/index.js
import { View } from 'remax-one';
import showToast from '@/api/showToast';

export default () => {
  return (
    <View
      onClick={() => {
        showToast({ content: 'Hello World!' });
      }}
    >
      CLICK ME!
    </View>
  );
};

remax-cli 会优先读取 [target].js 文件,这个规则针对 CSS 等其他文件同样有效。

组件

如上面所说,我们非常克制谨慎地对 remax/one 中提供的组件做了筛选和重新设计,只保留了我们能保证在各个平台之间行为一致的组件和属性。

如果需要使用某个平台特有的组件,可以直接从对应平台导入。如:

import * as React from 'react';
import { View, Text } from 'remax/one';
import { ScrollView } from 'remax/wechat';

export default () => {
  return (
    <ScrollView>
      <View>view</View>
      <Text>text</Text>
    </ScrollView>
  );
};

如果需要使用某个平台特有的属性,可以通过 {平台前缀}-{平台原生属性名称} 来设置,例如:

import * as React from 'react';
import { View, TapEvent } from 'remax-one';

export default () => {
  return (
    <View
      id="id"
      className="class"
      alipay-onAppear={() => {}}
      wechat-bindanimationend={() => {}}
      wechat-disable-scroll={true}
      onTap={(event: TapEvent) => {
        console.log(event);
      }}
    >
      view
    </View>
  );
};

通过 Remax One 开发者可以非常方便地构建跨小程序平台的应用。

另外社区同学开发的跨平台组件也正在路上:github.com/AnnaSearl/a…