相關進展: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 Roadmapapp
mxflutter 是一個標準的 Dart package,能夠按照 Dart 引入 package 的方式接入,步驟很是簡單。在開始接入以前,運行體驗 mxfltuter 的兩個例子,對接入會有幫助,一個是示例豐富但比較複雜的例子,在 github.com/mxflutter/m… 主庫根目錄,一個是最簡化接入示例,在主庫 mxflutter/example/ 目錄下 ,推薦第一次接入按照第二個例子來。框架
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… 來接入,方面本身修改和按期從主庫的更新。post
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