Flutter Web 與 JS 或 React 通信交互

Flutter Web 的資料真的是太少了啊,可以說(shuō)是幾乎沒(méi)有。

Flutter Web 很多庫(kù)基本都用不了映皆。比如 WebView 的庫(kù),與JS交互准脂,使用原生的方法根本走不通劫扒。


瀏覽器的項(xiàng)目還是要用前端JS的方式解決。經(jīng)過(guò)了一通折騰狸膏,皇天不負(fù)苦心人沟饥,終于是把路走通了。

目錄
1. 與原生JS交互
    1.1 Flutter 調(diào)用 Js湾戳;
    1.2 Js 調(diào)用 Flutter贤旷;
2. 與React交互
    2.1 Flutter 調(diào)用 React 的 Js 方法;
    2.2 React 調(diào)用 Flutter 的方法砾脑。

先引入 Flutter 的 JS 庫(kù):https://pub.dev/packages/js

dependencies:
  js: ^0.6.7

一幼驶、與原生JS交互

1. Flutter 調(diào)用 Js

1.1 先在 HTML 提供一個(gè) JS 方法:

js 的代碼可以寫(xiě)在 index.html 的代碼里:

方法如下:

function getPersonInfo() {
    const Person = {
        name: 'John',
        sex: 'women',
        age: 36,
    }
    const jsonString = JSON.stringify(Person)
    return jsonString;
}

1.2 在 Flutter 調(diào)用剛才的 JS 方法:

import 'dart:convert';
import 'package:flutter/material.dart';
import 'dart:js' as js;

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ElevatedButton(
        child: const Text("調(diào)用js代碼"),
        onPressed: () {
          // Flutter Web 調(diào)用 Js
          var personInfo = js.context.callMethod('getPersonInfo');
          print("personInfo is $personInfo");
        },
      )
    );
  }
}

至此,把 Flutter Web 項(xiàng)目運(yùn)行一下韧衣,就可以在控制臺(tái)看到運(yùn)行結(jié)果盅藻。
非常簡(jiǎn)單购桑。

2. Js 調(diào)用 Flutter 方法

先通過(guò) Flutter 在 js 的 window 中注入一個(gè)方法,然后在 js 中調(diào)用這個(gè)方法氏淑。

2.1 先在 Flutter 提供一個(gè)方法(詳見(jiàn)注釋?zhuān)?/h4>
import 'dart:convert';
import 'package:flutter/material.dart';
import 'dart:js' as js;

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  // Toast 顯示提示信息 - 提供給 JS 的方法
  void toastMsg(String msg) {
    print("address: $msg");
    MyUtils.showToast(msg);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ElevatedButton(
        child: const Text("調(diào)用js代碼"),
        onPressed: () {
          // 給 JS 提供一個(gè)方法勃蜘。 js 通過(guò) window 調(diào)用
          js.context["toastMsg"] = toastMsg;

          // Flutter Web 調(diào)用 Js
          js.context.callMethod('showVersion');
        },
      )
    );
  }
}

2.2 Js端的代碼:

function showVersion() {
    // 調(diào)用 Flutter 提供的方法
    window.toastMsg("當(dāng)前版本號(hào)為:1.0.0");
}

至此,就實(shí)現(xiàn)了 Flutter 與 原生JS 的彼此交互假残。


原生JS基本只能實(shí)現(xiàn)最基礎(chǔ)的邏輯缭贡,只掌握到這一步幾乎毫無(wú)意義。目前絕大多數(shù)的項(xiàng)目都是 React 或 Vue 框架寫(xiě)的辉懒,React 的方法與原生JS還是有一些區(qū)別阳惹。接下來(lái)看一下與 React 的方法交互。

二眶俩、Flutter 與 React 交互

學(xué)習(xí)了上面的方法之后莹汤,應(yīng)該已經(jīng)明白了其中的原理。 真正做的時(shí)候仿便,就會(huì)發(fā)現(xiàn)有一個(gè)難點(diǎn):React框架打包之后体啰,會(huì)對(duì)之前的JS方法名進(jìn)行壓縮處理攒巍,之前的方法名就變了嗽仪,會(huì) not found。所以柒莉,這里主要處理的就是 React 打包之后如何調(diào)用原始的方法闻坚。

上面已經(jīng)知道如何互相交互了,這里就簡(jiǎn)單點(diǎn)兢孝,只列出關(guān)鍵點(diǎn)窿凤。

1. 在 React 中編寫(xiě)方法供 Flutter調(diào)用

React 可以做一些自己業(yè)務(wù),最終打包跨蟹,將打包之后的項(xiàng)目移至 Flutter Web 的項(xiàng)目中雳殊。

關(guān)鍵點(diǎn)如下:

window自定義聲明:

declare global {
    interface Window {
        toastMsg: Function;
    }
}

關(guān)鍵方法:

const getAddress = async () => {
    // ...
    // 網(wǎng)絡(luò)請(qǐng)求
    // ...
    const  ads = "請(qǐng)求結(jié)果";
    setAddress(ads);

    if (typeof window["toastMsg"] === "function") {
        window.toastMsg(address);
    }

    return address ? address : "未登錄";
};

// 提供給 Flutter 的方法
window["getMyAddress"] = async () => {
    return await getAddress();
};

2. 將 React 打包,把關(guān)鍵信息復(fù)制到 Flutter Web 項(xiàng)目中

2.1 React 打包

2.2 將這些文件復(fù)制

2.3 將關(guān)鍵文件復(fù)制到 Flutter 項(xiàng)目

2.4 在 Flutter 中調(diào)用方法

@JS()
external getMyAddress();
// 暴露給JS的方法
void toastMsg(String msg) {
  print("address: $msg");
  MyUtils.showToast(msg);
}

Widget buildMine() {
  return Container(
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        TextButton(
          onPressed: () {
            // 將方法暴露給 js 的 window
            js.context["toastMsg"] = toastMsg;

            // 調(diào)用 JS 方法
            var personInfo = js.context.callMethod('getMyAddress');
            print("getAddress is $personInfo");
          },
          child: Text("js2PersonInfo"),
        ),
        SizedBox(height: 20),
        TextButton(
          onPressed: () async {
            // 調(diào)用Js的方法
            try {
              var promise = getMyAddress();
              var result = await promiseToFuture(promise); // 第三個(gè)坑
              print("getAddress is $result");
            } catch (e) {
              print("getDeviceInfo錯(cuò)誤信息是 $e");
            }
          },
          child: Text("getMyAddress"),
        ),
        SizedBox(height: 20),
      ],
    ),
  );
}

注意:

至此窗轩,就實(shí)現(xiàn)了 Flutter Web 與 React 的交互夯秃。列出關(guān)鍵點(diǎn)記錄,以便后續(xù)使用痢艺。


不僅單單是交互仓洼。

以此方式,還可以彌補(bǔ)一些 Flutter 非常大的一個(gè)劣勢(shì):網(wǎng)頁(yè)首次打開(kāi)堤舒,非常緩慢色建。

可以使用 React 實(shí)現(xiàn)一些動(dòng)畫(huà),或者加載初始的界面舌缤,F(xiàn)lutter也會(huì)在同步加載箕戳。

結(jié)束某残。

如果有什么錯(cuò)誤,或者有更好的實(shí)現(xiàn)方式陵吸,歡迎討論驾锰。

參考:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市走越,隨后出現(xiàn)的幾起案子椭豫,更是在濱河造成了極大的恐慌,老刑警劉巖旨指,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赏酥,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡谆构,警方通過(guò)查閱死者的電腦和手機(jī)裸扶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)搬素,“玉大人呵晨,你說(shuō)我怎么就攤上這事“境撸” “怎么了摸屠?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)粱哼。 經(jīng)常有香客問(wèn)我季二,道長(zhǎng),這世上最難降的妖魔是什么揭措? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任胯舷,我火速辦了婚禮,結(jié)果婚禮上绊含,老公的妹妹穿的比我還像新娘桑嘶。我一直安慰自己,他們只是感情好躬充,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布逃顶。 她就那樣靜靜地躺著,像睡著了一般麻裳。 火紅的嫁衣襯著肌膚如雪口蝠。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,268評(píng)論 1 309
  • 那天津坑,我揣著相機(jī)與錄音妙蔗,去河邊找鬼。 笑死疆瑰,一個(gè)胖子當(dāng)著我的面吹牛眉反,可吹牛的內(nèi)容都是我干的昙啄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼寸五,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼梳凛!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起梳杏,我...
    開(kāi)封第一講書(shū)人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤韧拒,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后十性,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體叛溢,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年劲适,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了楷掉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡霞势,死狀恐怖烹植,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情愕贡,我是刑警寧澤草雕,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站颂鸿,受9級(jí)特大地震影響促绵,放射性物質(zhì)發(fā)生泄漏攒庵。R本人自食惡果不足惜嘴纺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望浓冒。 院中可真熱鬧栽渴,春花似錦、人聲如沸稳懒。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)场梆。三九已至墅冷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間或油,已是汗流浹背寞忿。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留顶岸,地道東北人腔彰。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓叫编,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親霹抛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子搓逾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容