Flutter是一種新型的「客戶端」技術。它的最終目標是替代包含幾乎全部平臺的開發:iOS,Android,Web,桌面;作到了一次編寫,多處運行。掌握Flutter web多是Web前端開發者翻盤的惟一機會。css
在前些日子舉辦的Google IO 2019 年度開發者大會上,Flutter web做爲一個很亮眼的技術受到了開發者的追捧。這是繼Flutter支持Android、IOS等設備以後,又一個里程碑式的版本,後續還會支持windows、linux、Macos、chroms等其餘嵌入式設備。Flutter自己是一個相似於RN、WEEX、hHybrid等多端統一跨平臺解決方案,真正作到了一次編寫,多處運行,它的發展超出了不少人的想象,值得前端開發者去關注,今天咱們來體驗一下Flutter Web。html
先了解一下Flutter, 它是一個由谷歌開發的開源移動應用軟件開發工具包,用於爲Android和iOS開發應用,同時也將是Google Fuchsia下開發應用的主要工具。自從FLutter 1.5.4版本以後,支持了Web端的開發。它採用Dart語言來進行開發,與JavaScript相比,Dart在 JIT(即時編譯)模式下,速度與 JavaScript基本持平。可是當Dart以 AOT模式運行時,Dart性能要高於JavaScript。前端
Flutter內置了UI界面,與Hybrid App、React Native這些跨平臺技術不一樣,Flutter既沒有使用WebView,也沒有使用各個平臺的原生控件,而是自己實現一個統一接口的渲染引擎來繪製UI,Dart直接編譯成了二進制文件,這樣作能夠保證不一樣平臺UI的一致性。它也能夠複用Java、Kotlin、Swift或OC代碼,訪問Android和iOS上的原生系統功能,好比藍牙、相機、WiFi等等。咱們公司的Now直播、企鵝輔導等項目、阿里的閒魚等商業化項目已經大量在使用。java
Flutter的頂層是用drat編寫的框架,包含Material(Android風格UI)和Cupertino(iOS風格)的UI界面,下面是通用的Widgets(組件),以後是一些動畫、繪製、渲染、手勢庫等。 框架下面是引擎,主要用C / C ++編寫,引擎包含三個核心庫,Skia是Flutter的2D渲染引擎,它是Google的一個2D圖形處理函數庫,包含字型、座標轉換,以及點陣圖,都有高效能且簡潔的表現。Skia是跨平臺的,並提供了很是友好的API。第二是Dart 運行時環境以及第三文本渲染布局引擎。 最底層的嵌入層,它所關心的是如何將圖片組合到屏幕上,渲染變成像素。這一層的功能是用來解決跨平臺的。linux
瞭解了FLutter 以後,我來講一下今天的重頭戲,Flutter for Web。要想知道Flutter爲何能在web上運行,得先來看看它的架構。android
經過對比,能夠發現,web框架層和mobile的幾乎如出一轍。所以只須要從新實現一下引擎和嵌入層,不用變更Flutter API就能夠徹底能夠將UI代碼從Android / IOS Flutter App移植到Web。Dart可以使用Dart2Js編譯器把Dart代碼編譯成Js代碼。大多數原生App元素可以經過DOM實現,DOM實現不了的元素能夠經過Canvas來實現。git
Flutter Web開發環境搭建,以個人windows環境爲例進行講解,其餘環境相似,安裝環境比較繁瑣,須要耐心,有Android開發經驗最好。github
對於Java程序開發而言,主要會使用JDK的兩個命令:javac.exe、java.exe。路徑:C:\Java\jdk1.8.0_181bin。可是這些命令因爲不屬於windows本身的命令,因此要想使用,就須要進行路徑配置。單擊「計算機-屬性-高級系統設置」,單擊「環境變量」。在「系統變量」欄下單擊「新建」,建立新的系統環境變量(或用戶變量,等效)。web
(1)新建->變量名"JAVA_HOME",變量值"C:\Java\jdk1.8.0_181"(即JDK的安裝路徑) (2)編輯->變量名"Path",在原變量值的最後面加上「;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin」 (3)新建->變量名「CLASSPATH」,變量值「.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar」chrome
安裝完成以後設置代理,左上角的File-》setting-》搜索proxy,設置公司代理,用來加速下載Android SDK。
以後點擊右上角方盒按鈕(SDK Manager),用來選擇安裝SDK版本,最好選Android 9版本,API28,會有一個很長時間的下載過程。SDK是開發必須的代碼庫。默認狀況下,Flutter使用的Android SDK版本是基於你的 adb (Android Debug Bridge,管理鏈接手機,已打包在SDK)工具版本。 若是您想讓Flutter使用不一樣版本的Android SDK,則必須將該 ANDROID_HOME 環境變量設置爲SDK安裝目錄。
右上角有個小手機類型的按鈕(AVD Manager),用來設置Android模擬器,建立一個虛擬機。若是你有一臺安卓手機,也能夠鏈接USB接口,替代虛擬機。這個過程是調試必須的。安裝完成以後,在 AVD (Android Virtual Device Manager) 中,點擊工具欄的 Run。模擬器啓動並顯示所選操做系統版本或設備的啓動畫面。表明了正確安裝。
下載Flutter SDK有多種方法,看看哪一種更適合本身: Flutter官網下載最新Beta版本的進行安裝:flutter.dev/docs/develo… 也可Flutter github項目中去下載,地址爲:github.com/flutter/flu… 版本越新越好,不要低於1.5.4。
將安裝包zip解壓到你想安裝Flutter SDK的路徑(如:C:\src\flutter;注意,不要將flutter安裝到須要一些高權限的路徑如C:\Program Files\)。記住,以後往環境變量的path中添加;C:\src\flutter\bin,以便於你能在命令行中使用flutter。
使用鏡像 因爲在國內安裝Flutter相關的依賴可能會受到限制,Flutter官方爲中國開發者搭建了臨時鏡像,你們能夠將以下環境變量加入到用戶環境變量中: PUB_HOSTED_URL:https://pub.flutter-io.cn
FLUTTER_STORAGE_BASE_URL: https://storage.flutter-io.cn
Pub是Dart的包管理工具,相似npm,捆綁安裝。 Dart安裝版地址:www.gekorm.com/dart-window… 默認安裝便可,安裝以後記住Dart的路徑,而且配置到環境變量path中,以便於能夠在命令行中使用dart與pub,默認的路徑是:C:\Program Files\Dart\dart-sdk\bin 先安裝stagehand,stagehand是建立項目必須的工具。查看一下C:\Users\chunpengliu\AppData\Roaming\Pub\Cache\bin
目錄下是否包含stagehand和webdev,若是有,添加到環境變量的path裏面,若是沒有,按下面方法安裝:
pub global activate stagehand
複製代碼
webdev是一個相似於Koa的web服務器,執行如下命令安裝
pub global activate webdev
# or
flutter packages pub global activate webdev
複製代碼
Flutter插件是用來支持Flutter開發工做流 (運行、調試、熱重載等)。 Dart插件 提供代碼分析 (輸入代碼時進行驗證、代碼補全等)。Android Studio的設置在File-》setting-》plugins-》搜索Flutter和Dart,安裝以後重啓。
VS code的設置在extension-》搜索Flutter和Dart,安裝以後重啓。
打開一個新的命令提示符或PowerShell窗口並運行如下命令以查看是否須要安裝任何依賴項來完成安裝:
flutter doctor
複製代碼
這是一個漫長的過程,flutter會檢測你的環境,並安裝全部的依賴,直至:No issues found!,若是有缺失,會就會再那一項前面打x。你須要一一解決。
一切就緒!
調用 View>Command Palette…(快捷鍵ctrl+shift+p) 輸入 ‘flutter’, 而後選擇 ‘Flutter: New web Project’
輸入 Project 名稱 (如flutterweb), 而後按回車鍵 指定放置項目的位置,而後按藍色的肯定按鈕 等待項目建立繼續,並顯示main.dart文件。到此,一個Demo建立完成。
咱們看到了熟悉的HTML文件以及項目入口文件main.dart。 web目錄下的index.html是項目的入口文件。main.dart初始化文件,圖片相關資源放在此目錄。 lib目錄下的main.dart,是主程序代碼所在的地方。 每一個pub包或者Flutter項目都包含一個pubspec.yaml。它包含與此項目相關的依賴項和元數據。 analysis_options.yaml是配置項目的lint規則。 /dart_tool 是項目打包運行編譯生成的文件,頁面主程序main.dart.js就在其中。
webdev flutterweb
複製代碼
編譯、打包完成以後,自動啓動(或者按F5)默認瀏覽器,看一下轉換後的HTML頁面結構:
lib/main.dart是主程序,源碼很是簡單,整個頁面用widgets堆疊而成,區別於傳統的html和css。
import 'package:flutter_web/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Hello, World!',
),
],
),
),
);
}
}
複製代碼
區別與flutter App應用,咱們導入的是flutter_web/material.dart庫而非flutter/material.dart,這是由於目前App的接口並不是和Web的徹底通用,不過隨着谷歌開發的繼續,它們最終會被合併到一塊。 打開pubspec.yaml(相似於package.json),能夠看到只有兩個依賴包flutter_web和flutter_web_ui,這兩個都已在github上開源。dev的依賴頁很是少,兩個編譯相關的包,和一個靜態文件分析包。
name: flutterweb
description: An app built using Flutter for web
environment:
# You must be using Flutter >=1.5.0 or Dart >=2.3.0
sdk: '>=2.3.0-dev.0.1 <3.0.0'
dependencies:
flutter_web: any
flutter_web_ui: any
dev_dependencies:
build_runner: ^1.4.0
build_web_compilers: ^2.0.0
pedantic: ^1.0.0
dependency_overrides:
flutter_web:
git:
url: https://github.com/flutter/flutter_web
path: packages/flutter_web
flutter_web_ui:
git:
url: https://github.com/flutter/flutter_web
path: packages/flutter_web_ui
複製代碼
接下來,咱們建立一個具備圖文功能的下載,根據實例來學習flutter,咱們將實現下圖的頁面。它是一個上下兩欄的佈局,下欄又分爲左右兩欄。
第一步:更改主應用內容,打開lib/main.dart文件,替換class MyApp,首先是根組件MyApp,它是一個類組件繼承自無狀態組件,是項目的主題配置,在home屬性中調用了Home組件:
class MyApp extends StatelessWidget {
// 應用的根組件
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '騰訊新聞客戶端下載頁', //meta 裏的titile
debugShowCheckedModeBanner: false, // 關閉調試bar
theme: ThemeData(
primarySwatch: Colors.blue, // 頁面主題 Material風格
),
home: Home(), // 啓動首頁
);
}
}
複製代碼
第二步,在Home類中,是咱們要渲染的頁面頂導,運用了AppBar組件,它包括了一個居中的頁面標題和居右的搜索按鈕。文本能夠像css同樣設置外觀樣式。
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0.0,
centerTitle: true,
title: Text( // 中心文本
"下載頁",
style:
TextStyle(color: Colors.black, fontSize: 16.0, fontWeight: FontWeight.w500),
),
// 搜索圖標及特性
actions: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Icon(
Icons.search,
color: Colors.black,
),
)
],
),
//調用body渲染類,此處能夠添加多個方法調用
body: Stack(
children: [
Body()
],
),
);
}
}
複製代碼
第三步,建立頁面主體內容,一張圖加多個文本,使用了文本組件和圖片組件,頁面結構採用了flex佈局,因爲兩個Expanded的Flex值均爲1,所以將在兩個組件之間平均分配空間。SizedBox組件至關於一個空盒子,用來設置margin的距離
class Body extends StatelessWidget {
const Body({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded( // 左側
flex: 1,
child: Image.asset(// 圖片組件
"background-image.jpg", // 這是一張在web/asserts/下的背景圖
fit: BoxFit.contain,
),
),
const SizedBox(width: 90.0),
Expanded( // 右側
flex:1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text( // 文本組件
"騰訊新聞",
style: TextStyle(
color: Colors.black, fontWeight: FontWeight.w600, fontSize: 50.0, fontFamily: 'Merriweather'),
),
const SizedBox(height: 14.0),// SizedBox用來增長間距
Text(
"騰訊新聞是騰訊公司爲用戶打造的一款全天候、全方位、及時報道的新聞產品,爲用戶提供高效優質的資訊、視頻和直播服務。資訊超新超全,內容獨家優質,話題評論互動。",
style: TextStyle(
color: Colors.black, fontWeight: FontWeight.w400, fontSize: 24.0, fontFamily: "Microsoft Yahei"),
textAlign: TextAlign.justify,
),
const SizedBox(height: 20.0),
FlatButton(
onPressed: () {}, // 下載按鈕的響應事件
color: Color(0xFFCFE8E4),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Text("點擊下載", style: TextStyle(fontFamily: "Open Sans")),
),
),
],
),
),
const SizedBox(width: 100.0),
],
);
}
}
複製代碼
到此,頁面建立結束,保存,運行webdev serve,就能夠看到效果了。
FLutter web是Flutter 的一個分支,在開發完App以後,UI層面的FLutter代碼在不修改的狀況下能夠直接編譯爲Web版,基本能夠作到代碼100%複用,體驗還不錯。目前Flutter web做爲預覽版不管從性能上、易用上仍是佈局上都超出了預期,觸摸體驗挺好,雖然體驗比APP差一些,可是比傳統的web要好不少。試想一下 Flutter 開發iOS 和Android的App 還免費贈送一份Web版,而且比傳統的web開發出來的體驗還好。Write once ,Run anywhere。何樂而不爲?
我以爲隨着谷歌的持續優化,等到正式版發佈以後,開發體驗愈來愈好,Flutter開發者會吃掉H5很大一部分份額。Flutter 可能會給目前客戶端的開發模式帶來一些變革以及分工的變化, Flutter目前的開發體驗不是很好, 可是潛力很大,值得前端人員去學習。
可是目前仍是有一部分問題,Flutter web是爲客戶端開發(尤爲是安卓)人員開發準備的,對於前端理解來講學習成本有點高。目前FLutter web和 flutter 仍是兩個項目,編譯環境也是分開的,須要在代碼裏面修改Flutter相關庫的引用爲Flutter_web,組件還不能達到徹底通用,這個谷歌承諾正在解決中,谷歌的最終目標是Web、移動App、桌面端win mac linux、以及嵌入式版的Flutter代碼庫之間保持100%的代碼可移植性。
我的感受,開發體驗還不太好,還有不少坑要去踩,版本變動很快。還有社區資源稀少的問題,須要必定長期的積累。兼容性問題,代碼轉換後大量使用了web components,除了chrome以外,兼容性仍是有些問題。
咱們在web開發過程當中,都見過或者使用過一些奇技淫巧,這種技術咱們統稱爲黑魔法,這些黑魔法散落在各個角落,爲了方便你們查閱和學習,咱們作了收集、整理和歸類,並在github上作了一個項目——awesome-blackmargic,但願各位愛鑽研的開發者可以喜歡,也但願你們能夠把本身的獨門絕技分享出來,若是有興趣能夠給咱們發pr。
若是你對Flutter感興趣,想進一步瞭解Flutter,加入咱們的QQ羣(784383520)吧!