美文网首页
Flutter Web 与 JS 或 React 通信交互

Flutter Web 与 JS 或 React 通信交互

作者: Wing_Li | 来源:发表于2023-12-13 21:39 被阅读0次

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

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


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

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

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

    dependencies:
      js: ^0.6.7
    

    一、与原生JS交互

    1. Flutter 调用 Js

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

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

    方法如下:

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

    1.2 在 Flutter 调用刚才的 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("调用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 提供一个方法(详见注释):

    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端的代码:

    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自定义声明:

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

    关键方法:

    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 中调用方法

    @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;
    
                // 调用 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也会在同步加载。

    结束。

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

    参考:

    相关文章

      网友评论

          本文标题:Flutter Web 与 JS 或 React 通信交互

          本文链接:https://www.haomeiwen.com/subject/hvligdtx.html