小程序作為一項(xiàng)非標(biāo)準(zhǔn)的技術(shù),各個(gè)小程序平臺(tái)之間雖然大體上相似,但依然有非常多的差異?!耙淮伍_(kāi)發(fā)多端運(yùn)行”當(dāng)然是非常美好的愿望,但我們?cè)谠O(shè)計(jì) Remax 之初就意識(shí)到各個(gè)小程序平臺(tái)之間的差異是無(wú)法被抹平的,因?yàn)闆](méi)有一個(gè)標(biāo)準(zhǔn)來(lái)指導(dǎo)我們?cè)撊绾文ㄆ竭@些差異。
所以我們?cè)谧铋_(kāi)始,為每個(gè)小程序平臺(tái)提供了獨(dú)立的基礎(chǔ)組件。開(kāi)發(fā)者如果要做跨平臺(tái)開(kāi)發(fā),需要自己去封裝基礎(chǔ)組件。但很快,我們也意識(shí)到這對(duì)開(kāi)發(fā)者來(lái)說(shuō)是一件很麻煩的事情,特別是后面我們要支持更多平臺(tái)的話。
受 CSS 屬性名前綴的啟發(fā),我們重新設(shè)計(jì)了 Remax 的跨平臺(tái)方案。我們非??酥频剡x取了 9 個(gè)基礎(chǔ)組件,抹平了他們之間非平臺(tái)私有的屬性,并且以屬性名前綴的方式來(lái)支持各個(gè)平臺(tái)私有的特性。我們希望開(kāi)發(fā)者在做跨平臺(tái)開(kāi)發(fā)時(shí)能清楚地意識(shí)到你寫(xiě)下的這行代碼只會(huì)在特定的平臺(tái)上生效。
Remax One 就是我們提供的跨平臺(tái)解決方案。通過(guò) remax/one
我們提供了跨平臺(tái)的組件。
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>);};
可以看到,對(duì)于 onTap
這樣通用的屬性我們進(jìn)行了統(tǒng)一,而支付寶獨(dú)有的 onAppear
屬性,則需要加上 alipay-
的前綴。
remax/one
是 1.19.0 以后引入的特性。
從模板創(chuàng)建:
$ npx degit remaxjs/template-one my-app$ cd my-app
或者在已有的項(xiàng)目中引入:
在 remax.config.js
中設(shè)置 one: true
來(lái)開(kāi)啟 Remax One。
// remax.config.jsmodule.export = {one: true,// 通過(guò)環(huán)境變量區(qū)分不同平臺(tái)的輸出目錄output: 'dist/' + process.env.REMAX_PLATFORM,};
app.config.js
以及頁(yè)面的 config.js
配置文件支持多端配置方式:
// app.config.jsconst title = '小程序標(biāo)題';const bgColor = '#fff';const pages = ['pages/index/index'];// 支付寶exports.alipay = {pages: ['pages/alipay/index', ...pages],window: {defaultTitle: 'Alipay Todo App',titleBarColor: backgroundColor,},};// 微信exports.wechat = {pages: ['pages/wechat/index', ...pages],window: {navigationBarTitleText: title,navigationBarBackgroundColor: backgroundColor,},};
如果沒(méi)有默認(rèn)導(dǎo)出,
remax-cli
就會(huì)去讀取對(duì)應(yīng)平臺(tái)的配置信息。
你可以通過(guò)創(chuàng)建不同平臺(tái)的同名文件來(lái)封裝跨平臺(tái)組件和 API。例如:
// src/api/showToast/index.jsimport { showToast } from 'remax/alipay';export default showToast;
// src/api/showToast/index.wechat.jsimport { showToast } from 'remax/wechat';export default options => {showToast({...options,title: options.content,});};
// src/pages/index.jsimport { View } from 'remax-one';import showToast from '@/api/showToast';export default () => {return (<ViewonClick={() => {showToast({ content: 'Hello World!' });}}>CLICK ME!</View>);};
remax-cli
會(huì)優(yōu)先讀取 [target].js
文件,這個(gè)規(guī)則針對(duì) CSS 等其他文件同樣有效。
注意:上面的例子中的
src/api/showToast/index.js
是必須的,也就是說(shuō)不能只提供帶有平臺(tái)后綴的文件。
如上面所說(shuō),我們非??酥浦?jǐn)慎地對(duì) remax/one
中提供的組件做了篩選和重新設(shè)計(jì),只保留了我們能保證在各個(gè)平臺(tái)之間行為一致的組件和屬性。
如果需要使用某個(gè)平臺(tái)特有的組件,可以直接從對(duì)應(yīng)平臺(tái)導(dǎo)入。如:
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>);};
如果需要使用某個(gè)平臺(tái)特有的屬性,可以通過(guò) {平臺(tái)前綴}-{平臺(tái)原生屬性名稱}
來(lái)設(shè)置,例如:
import * as React from 'react';import { View, TapEvent } from 'remax-one';export default () => {return (<Viewid="id"className="class"alipay-onAppear={() => {}}wechat-bindanimationend={() => {}}wechat-disable-scroll={true}onTap={(event: TapEvent) => {console.log(event);}}>view</View>);};
更多建議: