You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Web中Dart与JavaScript双向通信及状态监听方案咨询

解决方案

首先纠正认知误区

你开发的是Flutter Web应用,本身运行在浏览器环境,完全不需要用webview_flutter这类移动端WebView嵌套插件,这类插件本身就是为移动端原生应用设计的,不支持Web平台,你直接用Flutter官方提供的dart:js、dart:js_util、dart:html库就能实现所有需求,无需任何第三方依赖。


问题1:Flutter与JS双向通信实现(无需读取DOM元素)

1.1 Flutter主动传值给JS

你不需要让JS读取HTML输入框的值,直接改造JS函数,让它支持接收入参即可:

// 修改script.js中的createRoom、joinRoom函数,去掉DOM读取逻辑,改为接收参数
function createRoom(roomInput) {
    console.log("Creating Room")
    // 直接用传进来的参数,不需要读document.getElementById
    if (roomInput.trim() === "") {
        alert("Please enter room number")
        return;
    }
    room_id = PRE + roomInput + SUF;
    // 原有后续逻辑不变
}

function joinRoom(roomInput) {
    console.log("Joining Room")
    if (roomInput.trim() === "") {
        alert("Please enter room number")
        return;
    }
    room_id = PRE + roomInput + SUF;
    // 原有后续逻辑不变
}

Flutter侧直接传递自己管理的变量值即可,比如你用Flutter的TextField输入房间号,直接传控制器的值:

import 'dart:js' as js;

final _roomController = TextEditingController();

// 创建房间按钮点击逻辑
void _handleCreateRoom() {
  js.context.callMethod('createRoom', [_roomController.text]);
}

1.2 JS侧状态变化主动通知Flutter

你只需要在Flutter侧把回调方法注册到全局window对象上,JS侧触发对应回调即可实现状态监听:
第一步,Flutter侧注册回调:

import 'dart:js' as js;

bool _isScreenSharing = false;
String? _currentRoomId;

@override
void initState() {
  super.initState();
  // 注册监听屏幕共享状态变化的回调
  js.context['onScreenSharingStateChange'] = (bool isSharing) {
    setState(() {
      _isScreenSharing = isSharing;
    });
  };
  // 注册监听房间连接成功的回调
  js.context['onRoomConnected'] = (String roomId) {
    setState(() {
      _currentRoomId = roomId;
    });
  };
  // 注册监听通知消息的回调
  js.context['onNotify'] = (String msg) {
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
  };
}

第二步,修改JS代码,在状态变化位置触发回调:

// startScreenShare 中屏幕共享开启后加一行
screenSharing = true
window.onScreenSharingStateChange?.(true) // 新增

// stopScreenSharing 中屏幕共享关闭后加一行
screenSharing = false
window.onScreenSharingStateChange?.(false) // 新增

// peer.on('open') 回调中加一行
notify("Waiting for peer to join.")
window.onRoomConnected?.(room_id) // 新增

// notify 函数中加一行,把通知同步到Flutter侧
notification.hidden = false
window.onNotify?.(msg) // 新增

通过这种方式,JS侧的所有状态变化都可以主动同步到Flutter,完全不需要依赖DOM元素。


问题2:WebRTC页面嵌入Flutter Web实现

你不需要用任何第三方HTML渲染插件,有两种成熟方案可选:

方案1:直接复用现有HTML文件,用IFrame嵌入

把你现有的webRTC.html、script.js、styles.css都放到Flutter项目的web根目录下,然后用HtmlElementView嵌入IFrame即可:

import 'dart:html' as html;
import 'dart:ui_web' as ui_web;
import 'package:flutter/material.dart';

class WebRtcPage extends StatefulWidget {
  const WebRtcPage({super.key});

  @override
  State<WebRtcPage> createState() => _WebRtcPageState();
}

class _WebRtcPageState extends State<WebRtcPage> {
  @override
  void initState() {
    super.initState();
    // 注册IFrame视图
    ui_web.platformViewRegistry.registerViewFactory(
      'webrtc-iframe',
      (int viewId) => html.IFrameElement()
        ..src = 'webRTC.html'
        ..style.border = 'none'
        ..width = '100%'
        ..height = '100%',
    );
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: HtmlElementView(viewType: 'webrtc-iframe'),
    );
  }
}

如果需要调用IFrame内部的JS方法,只需拿到IFrame的contentWindow对象即可:

final iframe = html.document.querySelector('iframe') as html.IFrameElement;
iframe.contentWindow?.callMethod('createRoom', [_roomController.text]);

方案2:全Flutter重写UI,JS只保留PeerJS逻辑

把原来HTML里的视频、按钮等UI元素全部用Flutter Widget重写,script.js只保留PeerJS的核心逻辑,不涉及任何DOM操作,这种方案体验更符合Flutter设计规范,维护成本更低。


内容的提问来源于stack exchange,提问作者Mithson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 10:09:05