flutter web 与 js 通信

2,644 阅读3分钟

启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第15天,点击查看活动详情

Flutter系列文章列表

  1. 2022年了,你还不会flutter!!!
  2. Flutter 第一课---flutter特点及组件开发
  3. Flutter 第二课---组件生命周期和App生命周期
  4. Flutter 第三课---状态管理之Provide
  5. Flutter 第四课---路由管理
  6. Flutter 第五课 --- 包管理器和资源管理
  7. Flutter 第六课 --- flutter网络请求
  8. Flutter 第七课 --- flutter 网络封装
  9. Flutter 第八课 ---使用 Flutter 构建 Web 应用
  10. 如何正确的在flutter中添加webview
  11. flutter原生 与 js 交互

前言

在上一节中我们讲到了flutter原生与js之间的交互,答案也很简单,是通过第三方库webview来实现。那么今天我们来讲如何把flutter web(就是flutter 编译成web 项目,运行在浏览器端)与 js 是如何实现通信的。

说明:Flutter 调用JS 需要   import dart.js 作为支持,如果项目中一旦导入 dart.js 项目则无法运行打包App 了,就只能运行在浏览器中。

Flutter 调用 Js

flutter_web 端代码如下

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Bridge',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Bridge Home Page'),
    );
  }
}

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('js2PersonInfo');
          print("personInfo is $personInfo");
          debugPrint("Flutter调用JS端方法js2PersonInfo结果为:${jsonDecode(personInfo)}");
        },
      )
    );
  }
}

我们把这个项目通过flutter web build编译成web,可以在项目根目录下找到/build/web,然后部署在本地服务器中,有很多方案,这里比较简单的方法就是在web 文件下运行Node命令(npx serve),启动一个本地服务器。然后在webview中注入

fluuter_bridge 代码如下:

import 'package:flutter/material.dart';
import 'dart:io';
import 'package:webview_flutter/webview_flutter.dart';

class WebviewApp extends StatefulWidget {
  const WebviewApp({Key? key}) : super(key: key);

  @override
  State<WebviewApp> createState() => _WebviewAppState();
}

class _WebviewAppState extends State<WebviewApp> {

  @override
  void initState() {
    super.initState();
    if (Platform.isAndroid) WebView.platform = AndroidWebView();
  }


  @override
  Widget build(BuildContext context) {
    return const WebView(
      //  注入flutter web 代码
      initialUrl: 'http://192.168.0.44:3000/#/',
      javascriptMode: JavascriptMode.unrestricted,
    );
  }
}

js端调用方法

这个文件可以在根目录web/html中书写

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

Js 调用 Flutter

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

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Bridge',
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

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

class _MyHomePageState extends State<MyHomePage> {


  int add(int a, int b){
    return a + b;
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body: ElevatedButton(
        child: const Text("normal"),
        onPressed: () {
          js.context["add"]=add;
          var result = js.context.callMethod('test');
          debugPrint("Flutter调用JS端方法test结果为:$result");
        },
      )
    );
  }
}

js 端代码:

function test() {
   var sum = window.add(12,23);
   console.log("sum 的值为:",sum);
   return sum;
}

这样我们就完美实现了flutter web 与 js之间的通信,通过上一节文章,我们就完成了flutter、flutter web和 js 之间的通信了。在初次尝试通信时,我也很受打击,我很开心,自己最终坚持了下来,下节课我们来说所在fluuter 中如何调用一个js Promise,这个坑巨大,希望有兴趣的可以参与进来,一起探讨。