亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

一、項(xiàng)目背景

隨著小程序在用戶規(guī)模和商業(yè)化上取得的極大成功,各大平臺(tái)都推出了自己的小程序。然而這些平臺(tái)的小程序開發(fā)在語法上又不盡相同,不同平臺(tái)小程序代碼的維護(hù)需要投入很大的精力,在邏輯性上也很難達(dá)到統(tǒng)一的效果。雖然也有各種轉(zhuǎn)換工具可以基于某一個(gè)平臺(tái)轉(zhuǎn)換出其他平臺(tái)的代碼,但轉(zhuǎn)換的效果也是差強(qiáng)人意,往往還需要人工去修改。使用小程序跨端開發(fā)框架來實(shí)現(xiàn)一次開發(fā)、到處運(yùn)行以提升效率,已經(jīng)成為開發(fā)者強(qiáng)烈而迫切的需求。

目前,小程序跨端開發(fā)框架主要可以按照技術(shù)棧和實(shí)現(xiàn)原理兩個(gè)維度進(jìn)行分類。從技術(shù)棧來說,主流的跨端框架基本遵循 React、Vue 這兩個(gè)前端開發(fā)最常使用的框架。由于所在團(tuán)隊(duì)主要使用的是React,所以本文主要介紹采用React語法的框架。從實(shí)現(xiàn)原理上,開源社區(qū)的跨端框架可分為編譯時(shí)(compile time)和運(yùn)行時(shí)(runtime)。

主流框架及其特點(diǎn)介紹如下表1-1所示:

表1-1 React語法小程序跨端框架舉例

框架

廠家

特征

Kbone

騰訊

不限技術(shù)棧,微信小程序和 Web 端同構(gòu)的運(yùn)行時(shí)解決方案,模擬了一套dom和bom接口,用以兼容現(xiàn)有的前端體系,只能用于Web兼容微信小程序,無法滿足其他平臺(tái)小程序的開發(fā)

Taro1/2

京東

類React,靜態(tài)編譯型框架僅在開發(fā)時(shí)遵循React語法,編譯后運(yùn)行時(shí)與React無關(guān)

Nanachi

去哪兒

React,靜態(tài)編譯型框架

Rax

阿里巴巴

運(yùn)行時(shí)方案為基礎(chǔ),支持局部場景使用編譯時(shí)方案。運(yùn)行時(shí)的支持基于Kbone,使用的是類React語法的Rax框架

Remax

螞蟻金服

使用原生React來構(gòu)建小程序,運(yùn)行時(shí)框架,從Remax2.0開始支持Web應(yīng)用的構(gòu)建

Taro3

京東

不限技術(shù)棧,使用一套runtime層來兼容各種DSL,誕生于Remax之后

compile time編譯時(shí)的跨端框架,主要的工作量在編譯階段。框架會(huì)把用戶寫的業(yè)務(wù)代碼解析成 AST 樹,然后通過語法分析將用戶寫的原始代碼轉(zhuǎn)換成符合小程序規(guī)則的代碼。運(yùn)行時(shí)模式的跨端框架通過適配層,實(shí)現(xiàn)自定義渲染器,是真正的在小程序的邏輯層中運(yùn)行起React或Vue框架的方式,這種方式比靜態(tài)編譯有天然的優(yōu)勢。

編譯時(shí)主要存在以下問題:靈活的JSX語法既可以寫出非常復(fù)雜靈活的組件,同時(shí)也增加了編譯階段框架去分析和優(yōu)化的難度。這就導(dǎo)致適配工作量巨大,維護(hù)成本較高,即使這樣,也無法適配所有的寫法。例如京東的Taro 1/2 用窮舉的方式對 JSX 可能的寫法進(jìn)行了一一適配,但依然需要開發(fā)者遵循大量的語法約束,避免很多動(dòng)態(tài)寫法。否則代碼就不能正常編譯運(yùn)行,開發(fā)效率難以保證。此外,由于 DOM 和 BOM API 的缺失,Web 上累積的各種前端生態(tài),基本無法在編譯時(shí)小程序中復(fù)用。京東的 Taro 1/2 , 去哪兒的 Nanachi都屬于靜態(tài)編譯型的React或類React跨端框架。

與之相比,運(yùn)行時(shí)方案的優(yōu)勢就在于能直接復(fù)用現(xiàn)有的前端生態(tài)。拿Remax來說,它最大的優(yōu)勢是可以幾乎沒有限制的使用React的語法完成代碼編寫,正如它的口號(hào)一樣——使用真正React來構(gòu)建跨平臺(tái)小程序。此外,從Remax2.0開始,remax/one支持Web應(yīng)用的構(gòu)建。

我們團(tuán)隊(duì)做選型的時(shí)候Taro3還是待發(fā)布狀態(tài),所以沒有做太多的考慮,下面著重去比較一下Rax和Remax。Rax和Remax都是出自阿里系但兩個(gè)框架從設(shè)計(jì)思路上完全不同。

Remax從誕生之初就是為了支持小程序跨端框架Rax為了能盡量壓縮React體積對React進(jìn)行了重寫,又引入了Driver機(jī)制來適配多端,這就意味著Rax有額外的學(xué)習(xí)成本,并且Rax不能隨著React的迭代而更新。雖然Rax看似比較完善,提供了一套開箱即用的跨端API和完整的跨端UI控件支持,但它過多的依賴阿里的構(gòu)建體系,似乎不太適合做為開源框架的選擇。

綜合以上幾點(diǎn)考慮最終我們選擇了Remax。

二、效果展示

圖2-1到2-3分別為首頁,列表頁和詳情頁在Web和微信小程序上的運(yùn)行效果,實(shí)現(xiàn)了一套代碼多端運(yùn)行,同時(shí)能做到同步更新。

小程序跨端框架實(shí)踐之Remax篇

 

小程序跨端框架實(shí)踐之Remax篇

 

圖2-1 攜程船票首頁web和微信小程序運(yùn)行結(jié)果

小程序跨端框架實(shí)踐之Remax篇

 

小程序跨端框架實(shí)踐之Remax篇

 

圖2-2 攜程船票列表頁web和微信小程序運(yùn)行結(jié)果

小程序跨端框架實(shí)踐之Remax篇

 

小程序跨端框架實(shí)踐之Remax篇

 

圖2-3 攜程船票詳情頁web和微信小程序運(yùn)行結(jié)果

下面介紹一下Remax的基本用法。

三、基本用法

3.1 創(chuàng)建/安裝依賴/運(yùn)行

使用create-remax-App創(chuàng)建的小程序

npxcreate-remax-app my-app
? name my-app //填寫你的appName
? author test<[email protected]>
? descriptionRemax Project  //填寫項(xiàng)目描述
? platform 
? 跨平臺(tái)小程序
  微信小程序
  阿里(支付寶)小程序
  頭條小程序
  百度小程序

因?yàn)槲覀兘榻B的是跨端小程序,這里選擇跨平臺(tái)小程序。

運(yùn)行項(xiàng)目

cd my-app&& npm install
npm run dev web//web端預(yù)覽
npm run devwechat //微信小程序端

小程序端運(yùn)行后會(huì)在項(xiàng)目目錄里生成 dist/wechat、dist/ali各個(gè)小程序的產(chǎn)物,用小程序的IDE導(dǎo)入對應(yīng)的目錄即可預(yù)覽。

項(xiàng)目的目錄結(jié)構(gòu)大致如下:

小程序跨端框架實(shí)踐之Remax篇

 

其中public目錄在編譯時(shí)會(huì)被復(fù)制到dist目錄下,里面的原生頁面pages目錄也會(huì)和Remax的pages目錄合并,這一部分后面會(huì)詳細(xì)介紹。

3.2 Remax的跨平臺(tái)機(jī)制

以下詳細(xì)介紹Remax的跨平臺(tái)機(jī)制

小程序跨端框架實(shí)踐之Remax篇

 

以上就是一個(gè)頁面的基本文件目錄結(jié)構(gòu),但是我們翻一遍Remax的文檔就會(huì)發(fā)現(xiàn)它提供的跨平臺(tái)的接口是少之又少,只有9個(gè)組件以及5個(gè)路由相關(guān)的API。所以Remax又提供了一種用文件名后綴來區(qū)分不同平臺(tái)代碼的方法:

小程序跨端框架實(shí)踐之Remax篇

 

如上面的目錄所示,在頁面的目錄里增加相應(yīng)后綴的文件在build相應(yīng)平臺(tái)的時(shí)候就會(huì)優(yōu)先使用對應(yīng)后綴的文件。

Remax還提供了環(huán)境變量區(qū)分平臺(tái)的機(jī)制,在代碼中直接通過
process.env.REMAX_PLATFORM區(qū)分平臺(tái)。例如:

if (process.env.REMAX_PLATFORM==='wechat') {}

以上代碼在編譯后只會(huì)保留對應(yīng)平臺(tái)的部分,所以無需擔(dān)心兼容多平臺(tái)帶來額外的代碼size增加。

除了上面說到的9個(gè)跨平臺(tái)的組件和5個(gè)跨平臺(tái)的API外,Remax還可以直接使用各個(gè)平臺(tái)的組件及API,無需使用useComponents聲明。

import React from'react';
import { View } from'remax/one';
import NativeCard from'./native-card';//native-card 是一個(gè)原生自定義組件
// 組件
exportdefault () => (
  <View>
    <NativeCard />
  </View>
);
// API
if (process.env.REMAX_PLATFORM==='ali') {
    systemInfo = my.getSysyemInfoSync();
} elseif (process.env.REMAX_PLATFORM==='wechat') {
    systemInfo = my.getSysyemInfoSync();
}

根據(jù)以上機(jī)制我們就可以自定義出任何我們需要的跨平臺(tái)API及組件。

按照Remax的說法之所以不提供更多的跨平臺(tái)組件和API是因?yàn)樗麄冊谠O(shè)計(jì)之初沒有標(biāo)準(zhǔn)去抹平各個(gè)平臺(tái)的差異。這當(dāng)然給使用框架的開發(fā)者帶來了一些麻煩,許多的組件和API不能開箱即用,需要額外的去做一層封裝。但這也是Remax這個(gè)框架的優(yōu)勢,只保留了核心的組件及API使得它本身不占太多的size,也使得要兼容一個(gè)新的平臺(tái)變得非常容易。

四、實(shí)踐干貨

4.1混合原生

之前我們說到了public目錄里的原生代碼會(huì)拷貝到dist目錄并且pages目錄會(huì)合并,我們可以利用這一機(jī)制最大程度的復(fù)用現(xiàn)有小程序的代碼,這也是我們團(tuán)隊(duì)選擇Remax這個(gè)框架的原因之一。

讓我們來體驗(yàn)一下,先創(chuàng)建一個(gè)原生小程序,以微信小程序?yàn)槔?/p>

小程序的文件目錄大致如下

小程序跨端框架實(shí)踐之Remax篇

 

現(xiàn)在把整個(gè)小程序的代碼放入public目錄

小程序跨端框架實(shí)踐之Remax篇

 

此時(shí)npm run dev wechat就會(huì)把pages以及utils拷貝到dist目錄下并且pages目錄合并了。

小程序跨端框架實(shí)踐之Remax篇

 

雖然合并了,但是我們觀察一下發(fā)現(xiàn)原生小程序的app.json的內(nèi)容不見了,難道要在Remax里面把a(bǔ)pp.json都寫一遍么?帶著疑問我們仔細(xì)翻看Remax的文檔,發(fā)現(xiàn)remax.config.js里是可以配置動(dòng)態(tài)生成app.json的配置的:

onAppConfig() {
    ...
      // 獲取原始小程序配置originConfig和 remax app.config.js配置tmp
    // 做合并處理
    const appJSON =JSON.parse(JSON.stringify(originConfig));
    tmp.pages.forEach(function (item) {
        if (appJSON.pages.indexOf(item) ==-1) {
            appJSON.pages.push(item);
        }
    });
    tmp.subPackages.forEach(function (item) {
        let needAdd =true;
        for (let i =0, a = appJSON.subPackages; i < a.length; i++) {
            if (a[i].root=== item.root) {
                needAdd =false; a[i] = item;break;
            }
        }
        if (needAdd) {
            appJSON.subPackages.push(item);
        }
    });
    ...
    return appJSON;
}

經(jīng)過以上處理,原小程序的app.json內(nèi)容就和remax.config.js內(nèi)容合并了,以上代碼只處理了pages和subPackages,如果覺得還有什么需要合并的也可以在這里處理。此時(shí),build生成的產(chǎn)物app.json,就保留了原小程序的內(nèi)容并且合并了Remax小程序的內(nèi)容。

產(chǎn)物里的app.js也沒有原生小程序里的代碼,那原有的邏輯怎么辦呢。重新在Remax寫一遍嗎?大可不必。

我們可以自定義一個(gè)運(yùn)行時(shí)插件:

function createBothFun(remaxConfig, originConfig, key) {
    const remaxFun = remaxConfig[key];
    const originFun = originConfig[key];
    return function () {
        // 這里的this就是微信的app 里的this
        remaxFun.apply(this,arguments);
        originFun.apply(this,arguments);
    };
}
const lifeCycles=['onLaunch','onShow','onHide','onPageNotFound','onError']
function tryMergeConfig(remaxConfig, originConfig) {
    for (const key in originConfig) {
        if (key ==='constructor') {
            console.log('xxx');
        } elseif (lifeCycles.indexOf(key) >=0) {
            remaxConfig[key] =createBothFun(remaxConfig, originConfig, key);
        } else {
            remaxConfig[key] = originConfig[key];
        }
    }
}
const mergeConfig = (remaxConfig, originConfig) => {
    tryMergeConfig(remaxConfig, originConfig);
    return remaxConfig;
};
export default {
    onAppConfig({ config }) {
        let __app = App;
        let originConfig;
        App =function (origin) {
            originConfig = origin;
        };
        __non_webpack_require__('./app-origin.js');
        App = __app;
        //merge config
        config =mergeConfig(config, originConfig);
        const onLaunch = config.onLaunch;
        config.onLaunch= (...args) => {
            if (onLaunch) {
                onLaunch.apply(config, args);
            }
        };
        return config;
    },
};

把原來的app.js重命名為app-origin.js,然后在onAppConfig函數(shù)中使用__non_webpack_require__('./app-origin.js'); 請注意,這里的相對路徑是產(chǎn)物里的相對路徑,經(jīng)過以上一番操作后,我們的原小程序就可以真正和Remax混合運(yùn)行了。

但是這樣一來,我們的Remax似乎變得不能跨端了,因?yàn)樗荒芫幾g成你public目錄里放置的原生小程序類型。

難道混合和跨端只能是魚和熊掌不可兼得?后面我們將介紹使用工程化的方法來實(shí)現(xiàn)魚和熊掌兼得

4.2 Modal API化

你可能注意到了Remax的文檔里面列舉了10個(gè)控件,但我說它只有9個(gè)控件,官方的文檔上也說只有9個(gè)控件,為什么呢?因?yàn)镸odal嚴(yán)格的說來不能算是一個(gè)控件。

Modal實(shí)際上是調(diào)用createPortal這個(gè)API來創(chuàng)建一個(gè)節(jié)點(diǎn)覆蓋在其它內(nèi)容之上,在web端是使用的ReactDOM的createPortal,在小程序端是使用的@remax/runtime這個(gè)包里提供的同名方法。實(shí)際上portal在兩端掛載的位置也不太一樣,在Web端是直接的body上創(chuàng)建了一個(gè)新的div,而在小程序上則是掛在頁面實(shí)例一個(gè)叫modalContainer的節(jié)點(diǎn)。在實(shí)際使用中,使用Modal組件去顯示彈窗非常不方便,所以還是得把它變成API調(diào)用的方式。

以小程序端為例:

import...
import { createPortal } from'@remax/runtime';
import {ReactReconcilerInst } from'@remax/runtime/esm/render';


let createPortal__ = createPortal;
let ReactReconcilerInst__ = ReactReconcilerInst;
const styles = {
    modalContainer: {
        ...
    },
};
export default function withModal(TargetComponent) {
    const WrappedModalComponent = (props) => {
        const { mask,...other } = props;
        const component =useRef();
        const container =getCurrentPage().modalContainer;
        return createPortal__(
                  <View style={{ ...styles.modalContainer,pointerEvents: mask ?'auto':'none' }}>
                      <TargetComponent {...other} mask={mask} show={show} close={close} ref={component} />
                  </View>,
                  container
              )
    };
    WrappedModalComponent.hide= (conext) => {
        const container =getCurrentPage().modalContainer;
        if (container._rootContainer) {
            ReactReconcilerInst__.updateContainer(null, container._rootContainer,null,function () {
            });
        }
        container.applyUpdate();
    };
    WrappedModalComponent.show= (props) => {
        const container =getCurrentPage().modalContainer;
        if (!container._rootContainer) {
            container._rootContainer=ReactReconcilerInst__.createContainer(container,false,false);
        }
        const element = React.createElement(WrappedModalComponent, props);
        ReactReconcilerInst__.updateContainer(element, container._rootContainer,null,function () {
        });
        context.modalContainer.applyUpdate();
    };
    return WrappedModalComponent;
}
export { withModal };

使用示例:

//在需要彈窗的組件上使用withModal裝飾器
@withModal
export default MyComponent(props) {
  ...
  return<View>{...}</View>
}
//在不支持裝飾器的模式下也可以直接調(diào)用
function MyComponent(props) {
    ...
  return<View>{...}</View>
} 
const ModaledComponent =withModal(MyComponent)
//在需要使用彈窗的地方使用
ModaledComponent.show(props);//展示彈窗
ModaledComponent.hide();

4.3工程化

考慮到我們的小程序是多部門多團(tuán)隊(duì)共同合作的項(xiàng)目,不可能讓整個(gè)公司同時(shí)都使用Remax重寫原來的業(yè)務(wù),那樣會(huì)有極大不可控風(fēng)險(xiǎn)。所以Remax只能是在部分業(yè)務(wù)試用,并且能漸進(jìn)的切換原有的業(yè)務(wù),這就要求我們必須有工程化的方案。

我們期望的小程序產(chǎn)物的結(jié)構(gòu)如下:

小程序跨端框架實(shí)踐之Remax篇

 

而 Web 端的產(chǎn)物結(jié)構(gòu)如下:

小程序跨端框架實(shí)踐之Remax篇

 

這表示小程序端是依賴原有小程序的,Web端是可以單個(gè)業(yè)務(wù)單獨(dú)發(fā)布的,于是我們在編譯過程中給小程序和Web生成兩套不同的殼工程。

編譯小程序的過程中拉取殼工程,殼工程的目錄結(jié)構(gòu)大致如下:

小程序跨端框架實(shí)踐之Remax篇

 

其中remaxA和remaxB的頁面代碼是在拉取殼工程的時(shí)候動(dòng)態(tài)生成的,我們在殼工程里放入一個(gè)配置文件bundle.js,用來描述該殼工程有哪些Remax業(yè)務(wù)代碼:

module.exports= {
  remaxA: {
    git:"[email protected]"
  },
  remaxB: {
    gitL "[email protected]"   
    }
}

在拉取殼工程的同時(shí)clonebundle.js所配置的倉庫到臨時(shí)目錄packages,此時(shí)packages目錄如下:

小程序跨端框架實(shí)踐之Remax篇

 

然后根據(jù)Remax業(yè)務(wù)代碼里的app.config.js,重新在殼工程生成新的頁面和頁面配置,其核心邏輯如下:

const template = (projectName, path) => {
    return`import ${projectName} from'~packages/${projectName}/src/pages${path ?`/${path}`:''}';
${projectName}.prototype.onShareAppMessage;
${projectName}.prototype.onPageScroll;
${projectName}.prototype.onShareTimeline;
exportdefault ${projectName};
`;
}


const pageHandler = (projectName) => {
    const projectPath =`${rootDir}/packages/${projectName}`;
    shell.cd(projectPath);
    let conf =require(`${projectPath}/src/app.config.js`);
    let platConf = conf[platform] || conf;
    const projectAllPages = [];
    ...
    // 遍歷 pages 和subPackages配置并替換路徑
    pagePath.replace('pages/',`pages/${projectName}/`);
    ...
    subPackage.root= subPackage.root.replace('pages/',`pages/${projectName}/`);
    ...
    // 將pages subPackages里所有的頁面路徑合并到一起
    let allPages = [...platConf.pages]
    allPages.push(path.join(subPackage.root, page));
    // 遍歷頁面配置生成新的頁面
    allPages.forEach((mapPath) => {
        const pagePath = path.resolve(rootDir,'src','pages', projectName,`${mapPath}.js`);
        fse.ensureFileSync(pagePath);
        const data =template(projectName, mapPath);
        fs.writeFileSync(pagePath, data);
    });
};
const complier = () => {
    ...
    //獲取子項(xiàng)目git地址,下載至packages目錄下
    const packagesPath = path.resolve(rootDir,'packages');
    const subDirs = fs.readdirSync(packagesPath);
    // 遍歷packages根據(jù)packages里的app.config.js重新生成合并路徑后的頁面
    subDirs.forEach((name) => {
        let file = fs.statSync(`${packagesPath}/${name}`);
        if (file.isDirectory()) {
            pageHandler(name);
        }
    });
    ...
};
module.exports= complier

生成的頁面代碼如下:

import remaxA from'~packages/remaxA/src/pages/index/index';
remaxA.prototype.onShareAppMessage;
remaxA.prototype.onPageScroll;
remaxA.prototype.onShareTimeline;
exportdefault remaxA;

這個(gè)可以修改上面代碼中template按需求修改, 這段代碼中之所以有類似
remaxA.prototype.onShareAppMessage; 這樣的無用代碼是因?yàn)镽emax在編譯過程中會(huì)收集頁面代碼里的生命周期函數(shù)的關(guān)鍵字,非必需的生命周期在頁面代碼沒有出現(xiàn)的時(shí)候,編譯產(chǎn)物里也不會(huì)有。

生成的頁面路徑如下:

小程序跨端框架實(shí)踐之Remax篇

 

同樣的,在Web端也會(huì)有相似的操作。我們Web是使用node容器發(fā)布的,所以殼工程就弄成了node工程了。如果使用靜態(tài)發(fā)布那就不需要?dú)すこ塘耍苯觔uild發(fā)布產(chǎn)物就可以了。

此外,由于小程序的單包size限制的原因,在小程序webpack配置方面需要做一些額外的配置,避免多個(gè)Remax業(yè)務(wù)不共同依賴的代碼也打到主包去,導(dǎo)致主包的單包size超出限制,這里給一個(gè)例子,僅供參考:

 configWebpack:function (options) {
      let config = options.config;
      let subpackageGroups = {};
      Object.keys(projects).forEach((key) => {
          let packagePages = projectsPages[key];
          let allPages = packagePages.allPages.map((page) =>`pages/${key}/${page}`);
          let pages = packagePages.pages;
          subpackageGroups[`${key}Common`] = {
              name:`package-${key}-common`,
              test: (module) =>newRegExp(`[\/]packages[\/]${key}[\/]src[\/]`).test(module.userRequest),
              chunks:'all',
              minChunks:2,
              minSize:0,
              priority:91,
              filename:`pages/${key}/package-${key}-common.js`,
          };
      });
      config.optimization.merge({
          splitChunks: {
              maxAsyncRequests:100,
              maxInitialRequests:100,
              automaticNameDelimiter:'-',
              enforceSizeThreshold:50000,
              cacheGroups: {
                ...,
                ...subpackageGroups
              },
          },
      });
    },

五、經(jīng)驗(yàn)總結(jié)

  • 經(jīng)過實(shí)踐,我們發(fā)現(xiàn)Remax確實(shí)是可以做到一處編寫到處運(yùn)行的,不足之處是Remax沒有提供一整套開箱即用的跨端API和控件,使用這個(gè)框架可能會(huì)有較多的前期基礎(chǔ)工作。但這也是它的優(yōu)勢,核心的依賴少了,而且是完全開放的,不會(huì)說用它就會(huì)帶來一個(gè)全家桶的依賴。
  • 由于Remax實(shí)現(xiàn)原理的限制,在小程序上較復(fù)雜的頁面性能上會(huì)有不足。當(dāng)然這也是所有跨端框架存在的問題,好在可以通過使用自定原生組件的方式來解決。
  • Remax目前還不支持DOM、BOM接口,也不支持直接使用webhostcomponent 來編寫跨端小程序,所以要實(shí)現(xiàn)跨端的話還是需要對現(xiàn)有的React應(yīng)用做一定的改造。
  • Remax還不支持RN平臺(tái),說不支持并不是說不能支持,只是要兼容RN的話,可能還得在現(xiàn)有的React上做一些限制。比如RN對css的支持,以及要實(shí)現(xiàn)一整套的RN的控件來兼容web端及小程序端,這又使得Remax不那么純粹了。

六、寫在最后

本文旨在給大家提供一些新的思路,在選型方面應(yīng)該從多方面去考量,各個(gè)方案可能沒有明顯的好壞之分,適合的才是最好的。就拿Taro來說,得益于有官方團(tuán)隊(duì)的支持,Taro3的發(fā)展速度非常之快,各個(gè)方面都做的比較完善。而Remax社區(qū)似乎沒有那么活躍,所以發(fā)展速度相對來說比較慢。期待有更多的朋友來參與開源框架的貢獻(xiàn)。

【作者簡介】汽車票前端研發(fā)團(tuán)隊(duì),致力于提供更便捷更智慧的出行方式,關(guān)注前端技術(shù)方向的探索和實(shí)踐。

分享到:
標(biāo)簽:程序
用戶無頭像

網(wǎng)友整理

注冊時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評(píng)定2018-06-03

通用課目體育訓(xùn)練成績評(píng)定