相關進展:javascript
更多 MXFlutter 信息,請關注掘金 MXFlutter Team帳號的相關文章 MXFlutterjava
MXFlutter 自去年發佈預覽版以後,通過不斷優化和重構 v0.2.1 已在iOS 線上APP使用,同時支持 Android 平臺。因爲整個框架的複雜性,業務接入步驟繁多,近期通過一系列的改造和重構,現已重構爲標準的 Flutter Package,並在昨天上線官方 pub 庫 mxflutter v0.2.1,進一步簡化接入流程,能夠簡單三步接入現有項目,打開由JS編寫的MXFlutter頁面。歡迎小夥伴接入嚐鮮。能夠安裝編譯好的 Android 的包來體驗 MXFlutter_v0-1-2.apkios
MXFlutter 是一套基於 JavaScript 的 Flutter 動態化框架,是目前開源的最完整可用的動態化方案,它用極相似Dart的開發方式,經過編寫JavaScript 代碼,來開發 Flutter 應用。代碼開源在 MXFlutter Github ,更多細節在 基於JavaScript的Flutter框架詳細介紹。git
v0.2.1版本新特性github
整體目標和方向bash
MXFlutter 當前由於工程量龐大,人力有限,還有不少須要逐步修改優化的地方,更新計劃參照 MXFlutter Roadmapmarkdown
mxflutter 是一個標準的 Dart package,能夠按照 Dart 引入 package 的方式接入,步驟很是簡單。在開始接入以前,運行體驗 mxfltuter 的兩個例子,對接入會有幫助,一個是示例豐富但比較複雜的例子,在 github.com/mxflutter/m… 主庫根目錄,一個是最簡化接入示例,在主庫 mxflutter/example/ 目錄下 ,推薦第一次接入按照第二個例子來。app
mxflutter v0.2.1 對應Flutter 1.17.0 (Channel stable tag:v1.17.0)
框架
dependencies:
mxflutter: ^0.2.1
複製代碼
由於mxflutter在快速迭代,推薦 fork 在 github 的主庫 github.com/mxflutter/m… 來接入,方面本身修改和按期從主庫的更新。函數
dependencies:
mxflutter:
git:
url: https://github.com/mxflutter/mxflutter.git
path: mxflutter/
複製代碼
第一步拷貝JS代碼文件:mxflutter 主庫提供了JS代碼模版,拷貝主庫 mxflutter/example/mxflutter_js_src (github.com/mxflutter/m…) 文件夾到你的工程目錄,和pubspec.yaml文件同級。
第二步在 pubspec.yaml 文件中引入 mxflutter_js_src 代碼資源文件夾
flutter:
assets:
- mxflutter_js_src/
複製代碼
特別注意:第一步拷貝的文件夾和第二步導入的資源是配套的,由於 pubspec.yaml 導入資源時,不會自動導入子文件夾, 若是你是拷貝的主庫根目錄 github.com/mxflutter/m… 文件夾,要配套按照主庫 pubspec.yaml 的資源配置來引入,學習接入建議使用 mxflutter/example/mxflutter_js_src 的示例
完成後目錄結構應該是這樣的
my_flutter/
├── lib/
│ └── main.dart
└── pubspec.yaml
└── mxflutter_js_src/
│ └── main.js
│ └── home_page.js
│ └── js_dev_demo.js
│ └── mxjsbuilder_demo.js
複製代碼
在 main.dart 文件中,調用 runJSApp 啓動JSApp,runJSApp 函數若是不傳任何參數,默認會運行 mxflutter_js_src/mian.js 文件
//mxflutter import 'package:mxflutter/mxflutter.dart'; void main() { //-------1. MXFlutter 啓動--------- MXJSFlutter.getInstance().runJSApp(); runApp(MyApp()); } 複製代碼
在合適時機,好比用戶點擊界面時,打開JS頁面。
onTap: () { //-------2. MXFlutter push 一個使用MXFlutter框架編寫的頁面 Navigator.push( context, MaterialPageRoute( builder: (context) => MXJSPageWidget( jsWidgetName: "MXJSWidgetHomePage"))); } 複製代碼
上面代碼 MXJSPageWidget 的參數 jsWidgetName: "MXJSWidgetHomePage",在mxflutter_js_src/main.js MyApp::createJSWidgetWithName 函數中使用,用來標示打開哪一個JS頁面。
在 github.com/mxflutter/m… 主庫iOS工程或者主庫 mxflutter/example/ 目錄的例子中,AppDelegate.m 文件詳細註釋了若是打開模擬器熱重載。拷貝setupMXFlutterJSPath 函數,在 Flutter 插件註冊 [GeneratedPluginRegistrant registerWithRegistry:self]; 以前調用便可
- (void)setupMXFlutterJSPath{ ///mxflutter js代碼模擬器熱重載支持 ///把JS文件重定向到本地地址,簡單支持模擬器JS文件熱重載, ///僅支持模擬器環境使用 ///*發佈版本的熱更新,也使用一樣API設置爲你的JS代碼下載目錄 #if TARGET_IPHONE_SIMULATOR //業務JS代碼的熱重載 NSString *jsAppPath = nil; NSArray *jsAppSearchPathList = nil; ///mxflutter framework的開發者用來加快調試,如不須要修改mxflutter jsframework,無需設置jsFramewrokPath NSString *jsFramewrokPath = nil; ///1. 能夠直接修改定位到絕對路徑,但多人協做開發時,每一個人路徑不一樣須要,須要都配置,推薦第二種方法,配置PROJECT_DIR ///jsFramewrokPath = @「/Volumes/Data/Work/mxflutter2/mxflutter/js_lib」; ///jsAppPath = @"/Volumes/Data/Work/mxflutter2/mxflutter_js_src/" ///2. 能夠配置PROJECT_DIR,把JS代碼路徑地址重定向到開發機iMac地址,用來支持模擬器熱重載,支持多人協同,配置PROJECT_DIR方法以下。 ///XCode -> Build Settings -> Preprocessor Macros : Debug下增長 PROJECT_DIR=@\""$PROJECT_DIR\/"\" ///這是github https://github.com/TGIF-iMatrix/mxflutter.git 下的 flutter/example/ios 工程爲例子,js_lib的 ///物理路徑配置以下 #ifdef PROJECT_DIR //能夠根據本身的工程部署調整相對路徑 jsAppPath = [PROJECT_DIR stringByAppendingPathComponent:@"../mxflutter_js_src/"]; // jsAppSearchPathList = @[ [jsAppPath stringByAppendingPathComponent:@"app_demo/"], [jsAppPath stringByAppendingPathComponent:@"mxjsbuilder_demo/"] ]; jsFramewrokPath = [PROJECT_DIR stringByAppendingPathComponent:@"../../js_lib/"]; #endif //能夠調用[MXFlutterPlugin setJSFramewrokPath:jsFramewrokPath]; 設置jsframework到Documents你的下載目錄,支持framework的熱更新 if (jsFramewrokPath.length > 0) { [MXFlutterPlugin setJSFramewrokPath:jsFramewrokPath]; } if (jsAppPath.length > 0) { [MXFlutterPlugin setJSAppPath:jsAppPath jsAppSearchPathList:jsAppSearchPathList]; } #endif } 複製代碼
先看看使用效果,如下截圖是在MXFlutter框架下用JS開發,能夠把上面的源碼下載下來,裏面有完整的JS代碼示例:
單頁面演示
下面是UI截圖對應的JS代碼,沒錯,你沒有眼花,這個是 JavaScript 代碼,能夠在 MXFlutter 的運行時庫上渲染出 Flutter 的UI,(是否是很像Flutter裏面的組件代碼)!
class JSPestoPage extends MXJSWidget { constructor() { super("JSPestoPage"); this.recipes = recipeList; } build(context) { let statusBarHeight = 24; let mq = MediaQuery.of(context); if (mq) { statusBarHeight = mq.padding.top } let w = new Scaffold({ appBar: new AppBar({ title: new Text("Pesto Demo") }), floatingActionButton: new FloatingActionButton({ child: new Icon(new IconData(0xe3c9)), onPressed: function () { }, }), body: new CustomScrollView({ semanticChildCount: this.recipes.length, slivers: [ //this.buildAppBar(context, statusBarHeight), this.buildBody(context, statusBarHeight), ], }), //body:this.buildItems()[0] }); return w; } buildAppBar(context, statusBarHeight) { return SliverAppBar({ pinned: true, expandedHeight: _kAppBarHeight, actions: [ IconButton({ icon: new Icon(new IconData(1)), tooltip: 'Search', onPressed: function () { }, }), ], flexibleSpace: LayoutBuilder({ builder: function (context, constraints) { size = constraints.biggest; appBarHeight = size.height - statusBarHeight; t = (appBarHeight - kToolbarHeight) / (_kAppBarHeight - kToolbarHeight); extraPadding = new Tween({ begin: 10.0, end: 24.0 }).transform(t); logoHeight = appBarHeight - 1.5 * extraPadding; return Padding({ padding: EdgeInsets.only({ top: statusBarHeight + 0.5 * extraPadding, bottom: extraPadding, }), child: Center({ child: new Icon(new IconData(1)) }), }); }, }), }); } buildBody(context, statusBarHeight) { let mediaPadding = EdgeInsets.all(0); let mq = MediaQuery.of(context); if (mq) { mediaPadding = MediaQuery.of(context).padding; } let padding = EdgeInsets.only({ top: 8.0, left: 8.0 + mediaPadding.left, right: 8.0 + mediaPadding.right, bottom: 8.0 }); return new SliverPadding({ padding: padding, sliver: new SliverGrid({ gridDelegate: new SliverGridDelegateWithMaxCrossAxisExtent({ maxCrossAxisExtent: _kRecipePageMaxWidth, crossAxisSpacing: 8.0, mainAxisSpacing: 8.0, }), delegate: new SliverChildBuilderDelegate( function (context, index) { let recipe = this.recipes[index]; let w = new RecipeCard({ recipe: recipe, onTap: function () { showRecipePage(context, recipe); }, }); return w; }, { childCount: this.recipes.length, }), }), }); } 複製代碼
項目演示
源碼中還有更豐滿的示例,高仿知乎頁面JSFlutter版,能夠點此進入查看代碼:
下圖是對應的UI,已經接近在線上版直接使用了:
當前 MXFlutter 處於 Beta版本,由於工程量龐大,人力有限,還有不少須要逐步修改優化的地方,目前在高速迭代中,使用 MXFlutter 過程當中有任何問題,能夠加羣交流 QQ羣:747535761