在 Flutter Web 中从 JS 调用 Dart 方法

Posted

技术标签:

【中文标题】在 Flutter Web 中从 JS 调用 Dart 方法【英文标题】:Call Dart method from JS in Flutter Web 【发布时间】:2021-04-02 01:14:59 【问题描述】:

对于 Webview 相关功能,我使用方法通道通过原生 androidios 代码打开 Webview,并且我正在其中打开一个网站,我正在从 JS 回调到移动平台中的原生代码。 对于 Android,我提供了一个从 JS 调用其方法的类, 它看起来像这样:

webView.settings.javascriptEnabled = true
webView.addJavascriptInterface(WebAppInterface(this), "nativeCommunicator")

webView.loadUrl("SOME_URL")

…

class WebAppInterface(private val mContext: Activity) 
  @JavascriptInterface
  fun postMessage(text: String) 
    println("WebAppInterface.message($text)")
    //send back to flutter
  

从 js 到我的代码的回调似乎很简单。

现在我正在尝试在 Flutter Web 中执行此操作 我通过调用打开了网站

import 'package:js/js.dart';
...
js.context.callMethod('open', 'SOME_URL', '_self');

效果很好,现在我正在尝试通过创建此类来获取回调

@JS()
library native_communicator;

import 'package:js/js.dart';
@JS('nativeCommunicator')
class NativeCommunicator

 @JS('postMessage')
 external static set _postMessage(void Function(String text) f);


 @JS()
 external static void postMessage();



void setJSCallbackFunction(void Function(String text) postMessageFunction) 
 NativeCommunicator._postMessage = allowInterop(postMessageFunction);

我正在调用 setJSCallbackFunction 并将我的函数作为参数传递,但它不断给我运行时错误 它找不到'postMessage',我尝试了其他一些导致找不到'nativeCommunicator'错误的方法, 谁能指出如何正确地做到这一点? 我需要从 js 中调用一个 dart 方法。

【问题讨论】:

【参考方案1】:

我认为您正在从 dart:js 库中寻找 allowInterop 函数:https://api.flutter.dev/flutter/dart-js/dart-js-library.html

示例代码:

import 'dart:html';
import 'dart:js';
import 'package:js/js_util.dart';

String dartFunc(String str) 
  return 'Inside dartFunc: ' + str;


void main() 
  setProperty(window, 'dartFunc', allowInterop(dartFunc));
  runApp(MyApp());

【讨论】:

它就在我的代码中。请检查一下,您尝试过并且有工作样品吗? 抱歉,没注意到。我已经用一些示例代码更新了答案。 js怎么调用? 它是在全局window对象上定义的,所以你可以通过dartFuncwindow.dartFunc来引用它【参考方案2】:

使 Dart 函数可从 JavaScript 调用

如果您将 Dart 函数作为参数传递给 JavaScript API,请使用 allowInterop()allowInteropCaptureThis() 包装 Dart 函数。

要通过名称从 JavaScript 调用 Dart 函数,请使用带有 @JS() 注释的 setter。

示例:

@JS()
library callable_function;

import 'package:js/js.dart';

/// Allows assigning a function to be callable from `window.functionName()`
@JS('functionName')
external set _functionName(void Function() f);

void _someDartFunction() 
  print('Hello from Dart!');


void main() 
  _functionName = allowInterop(_someDartFunction);
  // JavaScript code may now call `functionName()` or `window.functionName()`.

来自package:js docs

变化 -

@JS()
library native_communicator;

import 'package:js/js.dart';
@JS('nativeCommunicator')
class NativeCommunicator

 @JS('postMessage')
 external static set _postMessage(void Function(String text) f);

// No need to do this as 'allowInterop()' will do the necessary.
//
// @JS()
// external static void postMessage();
//
// 

void setJSCallbackFunction(void Function(String text) postMessageFunction) 
 NativeCommunicator._postMessage = allowInterop(postMessageFunction);

import 'path/to/setJSCallbackFunction-file';

void main() 
    setJSCallbackFunction(param);

调试步骤

    寻找生成的js文件-build/web/main.dart.js 尝试使用搜索来定位函数。 (这里,postMessage) 如果你找不到它,那么你可能错过了一些注释或者可能没有在main() 中调用allowInterop() 如果您能够找到它但它不起作用,请检查您的 dart 函数并确保您传递了正确的参数。此外,请确保 dart.main.js 在范围内。
<script src"path/to/dart.main.js">
window.functionName(); // or functionName()
</script>

倾向于将js函数定义为顶层函数,可以用window.functionName()functionName()调用

【讨论】:

以上是关于在 Flutter Web 中从 JS 调用 Dart 方法的主要内容,如果未能解决你的问题,请参考以下文章

在 Flutter 中从 main() 调用 setState()

在 Flutter 中从 Firebase 读取数组 [重复]

如何在我的颤振应用程序中从 bing web search apiv7 获取图像

如何在swift中从.js文件中调用javascript函数

如果在Flutter Web项目中使用lottie动画

如果在Flutter Web项目中使用lottie动画