小程序作為一項非標(biāo)準(zhǔn)的技術(shù),各個小程序平臺之間雖然大體上相似,但依然有非常多的差異?!耙淮伍_發(fā)多端運行”當(dāng)然是非常美好的愿望,但我們在設(shè)計 Remax 之初就意識到各個小程序平臺之間的差異是無法被抹平的,因為沒有一個標(biāo)準(zhǔn)來指導(dǎo)我們該如何抹平這些差異。
所以我們在最開始,為每個小程序平臺提供了獨立的基礎(chǔ)組件。開發(fā)者如果要做跨平臺開發(fā),需要自己去封裝基礎(chǔ)組件。但很快,我們也意識到這對開發(fā)者來說是一件很麻煩的事情,特別是后面我們要支持更多平臺的話。
受 CSS 屬性名前綴的啟發(fā),我們重新設(shè)計了 Remax 的跨平臺方案。我們非??酥频剡x取了 9 個基礎(chǔ)組件,抹平了他們之間非平臺私有的屬性,并且以屬性名前綴的方式來支持各個平臺私有的特性。我們希望開發(fā)者在做跨平臺開發(fā)時能清楚地意識到你寫下的這行代碼只會在特定的平臺上生效。
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
這樣通用的屬性我們進(jìn)行了統(tǒng)一,而支付寶獨有的 onAppear
屬性,則需要加上 alipay-
的前綴。
remax/one
是 1.19.0 以后引入的特性。
從模板創(chuàng)建:
$ npx degit remaxjs/template-one my-app$ cd my-app
或者在已有的項目中引入:
在 remax.config.js
中設(shè)置 one: true
來開啟 Remax One。
// remax.config.jsmodule.export = {one: true,// 通過環(huán)境變量區(qū)分不同平臺的輸出目錄output: 'dist/' + process.env.REMAX_PLATFORM,};
app.config.js
以及頁面的 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,},};
如果沒有默認(rèn)導(dǎo)出,
remax-cli
就會去讀取對應(yīng)平臺的配置信息。
你可以通過創(chuàng)建不同平臺的同名文件來封裝跨平臺組件和 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
會優(yōu)先讀取 [target].js
文件,這個規(guī)則針對 CSS 等其他文件同樣有效。
注意:上面的例子中的
src/api/showToast/index.js
是必須的,也就是說不能只提供帶有平臺后綴的文件。
如上面所說,我們非??酥浦?jǐn)慎地對 remax/one
中提供的組件做了篩選和重新設(shè)計,只保留了我們能保證在各個平臺之間行為一致的組件和屬性。
如果需要使用某個平臺特有的組件,可以直接從對應(yīng)平臺導(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>);};
如果需要使用某個平臺特有的屬性,可以通過 {平臺前綴}-{平臺原生屬性名稱}
來設(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>);};
更多建議: