Flutter Web 与 React 或 JS 通信交互

Flutter Web 的资料真的是太少了啊,可以说是几乎没有。

Flutter Web 很多库基本都用不了。比如 WebView 的库,与JS交互,使用原生的方法根本走不通。

浏览器的项目还是要用前端JS的方式解决。经过了一通折腾,皇天不负苦心人,终于是把路走通了。

menu 复制代码
目录
1. 与原生JS交互
    1.1 Flutter 调用 Js;
    1.2 Js 调用 Flutter;
2. 与React交互
    2.1 Flutter 调用 React 的 Js 方法;
    2.2 React 调用 Flutter 的方法。

先引入 Flutter 的 JS 库:pub.dev/packages/js

yaml 复制代码
dependencies:
  js: ^0.6.7

一、与原生JS交互

1. Flutter 调用 Js

1.1 先在 HTML 提供一个 JS 方法:

js 的代码可以写在 index.html 的代码里:

方法如下:

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

1.2 在 Flutter 调用刚才的 JS 方法:

dart 复制代码
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("调用js代码"),
        onPressed: () {
          // Flutter Web 调用 Js
          var personInfo = js.context.callMethod('getPersonInfo');
          print("personInfo is $personInfo");
        },
      )
    );
  }
}

至此,把 Flutter Web 项目运行一下,就可以在控制台看到运行结果。 非常简单。

2. Js 调用 Flutter 方法

先通过 Flutter 在 js 的 window 中注入一个方法,然后在 js 中调用这个方法。

2.1 先在 Flutter 提供一个方法(详见注释):

dart 复制代码
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("调用js代码"),
        onPressed: () {
          // 给 JS 提供一个方法。 js 通过 window 调用
          js.context["toastMsg"] = toastMsg;

          // Flutter Web 调用 Js
          js.context.callMethod('showVersion');
        },
      )
    );
  }
}

2.2 Js端的代码:

js 复制代码
function showVersion() {
    // 调用 Flutter 提供的方法
    window.toastMsg("当前版本号为:1.0.0");
}

至此,就实现了 Flutter 与 原生JS 的彼此交互。


原生JS基本只能实现最基础的逻辑,只掌握到这一步几乎毫无意义。目前绝大多数的项目都是 React 或 Vue 框架写的,React 的方法与原生JS还是有一些区别。接下来看一下与 React 的方法交互。

二、Flutter 与 React 交互

学习了上面的方法之后,应该已经明白了其中的原理。 真正做的时候,就会发现有一个难点:React框架打包之后,会对之前的JS方法名进行压缩处理,之前的方法名就变了,会 not found。所以,这里主要处理的就是 React 打包之后如何调用原始的方法。

上面已经知道如何互相交互了,这里就简单点,只列出关键点。

1. 在 React 中编写方法供 Flutter调用

React 可以做一些自己业务,最终打包,将打包之后的项目移至 Flutter Web 的项目中。

关键点如下:

window自定义声明:

js 复制代码
declare global {
    interface Window {
        toastMsg: Function;
    }
}

关键方法:

javascript 复制代码
const getAddress = async () => {
    // ...
    // 网络请求
    // ...
    const  ads = "请求结果";
    setAddress(ads);

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

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

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

2. 将 React 打包,把关键信息复制到 Flutter Web 项目中

2.1 React 打包

2.2 将这些文件复制

2.3 将关键文件复制到 Flutter 项目

2.4 在 Flutter 中调用方法

dart 复制代码
@JS()
external getMyAddress();
dart 复制代码
// 暴露给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;

            // 调用 JS 方法
            var personInfo = js.context.callMethod('getMyAddress');
            print("getAddress is $personInfo");
          },
          child: Text("js2PersonInfo"),
        ),
        SizedBox(height: 20),
        TextButton(
          onPressed: () async {
            // 调用Js的方法
            try {
              var promise = getMyAddress();
              var result = await promiseToFuture(promise); // 第三个坑
              print("getAddress is $result");
            } catch (e) {
              print("getDeviceInfo错误信息是 $e");
            }
          },
          child: Text("getMyAddress"),
        ),
        SizedBox(height: 20),
      ],
    ),
  );
}

注意:

至此,就实现了 Flutter Web 与 React 的交互。列出关键点记录,以便后续使用。


不仅单单是交互。

以此方式,还可以弥补一些 Flutter 非常大的一个劣势:网页首次打开,非常缓慢。

可以使用 React 实现一些动画,或者加载初始的界面,Flutter也会在同步加载。

结束。

如果有什么错误,或者有更好的实现方式,欢迎讨论。

参考:

相关推荐
zhanghaisong_20155 分钟前
Caused by: org.attoparser.ParseException:
前端·javascript·html·thymeleaf
Eric_见嘉8 分钟前
真的能无限试(白)用(嫖)cursor 吗?
前端·visual studio code
DK七七38 分钟前
多端校园圈子论坛小程序,多个学校同时代理,校园小程序分展示后台管理源码
开发语言·前端·微信小程序·小程序·php
老赵的博客1 小时前
QSS 设置bug
前端·bug·音视频
Chikaoya1 小时前
项目中用户数据获取遇到bug
前端·typescript·vue·bug
南城夏季1 小时前
蓝领招聘二期笔记
前端·javascript·笔记
Huazie1 小时前
来花个几分钟,轻松掌握 Hexo Diversity 主题配置内容
前端·javascript·hexo
NoloveisGod1 小时前
Vue的基础使用
前端·javascript·vue.js
GISer_Jing1 小时前
前端系统设计面试题(二)Javascript\Vue
前端·javascript·vue.js
海上彼尚2 小时前
实现3D热力图
前端·javascript·3d