Flutter Web 中 JS 调用 Dart 方法

Dhr*_*ada 7 javascript flutter flutter-web

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

\n
webView.settings.javaScriptEnabled = true\nwebView.addJavascriptInterface(WebAppInterface(this), "nativeCommunicator")\n\nwebView.loadUrl("SOME_URL")\n\n\xe2\x80\xa6\n\nclass WebAppInterface(private val mContext: Activity) {\n\xc2\xa0\xc2\xa0@JavascriptInterface\n\xc2\xa0\xc2\xa0fun postMessage(text: String) {\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0println("WebAppInterface.message($text)")\n    //send back to flutter\n\xc2\xa0\xc2\xa0}\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这似乎是从 js 回调到我的代码的非常简单的方法。

\n

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

\n
import 'package:js/js.dart';\n...\njs.context.callMethod('open', 'SOME_URL', '_self');\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
@JS()\nlibrary native_communicator;\n\nimport 'package:js/js.dart';\n@JS('nativeCommunicator')\nclass NativeCommunicator{\n\n\xc2\xa0@JS('postMessage')\n\xc2\xa0external static set _postMessage(void Function(String text) f);\n\n\n\xc2\xa0@JS()\n\xc2\xa0external static void postMessage();\n\n}\n\nvoid setJSCallbackFunction(void Function(String text) postMessageFunction) {\n\xc2\xa0NativeCommunicator._postMessage = allowInterop(postMessageFunction);\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我正在调用 setJSCallbackFunction 并将我的函数作为参数传递,但它一直给我运行时错误\n它找不到 \xe2\x80\x98postMessage\xe2\x80\x99,我尝试了其他方法,导致找不到 \xe2 \x80\x98nativeCommunicator\xe2\x80\x99 错误,\n谁能指出如何正确执行此操作?\n我需要从 js 调用 dart 方法。

\n

sid*_*006 9

使 Dart 函数可从 JavaScript 调用

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

要使 Dart 函数可通过名称从 JavaScript 调用,请使用带有@JS().

样本:

@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()`.
}
Run Code Online (Sandbox Code Playgroud)

来自package:js文档

变化 -

@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);
}
Run Code Online (Sandbox Code Playgroud)
import 'path/to/setJSCallbackFunction-file';

void main() {
    setJSCallbackFunction(param);
}
Run Code Online (Sandbox Code Playgroud)

调试步骤

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

更喜欢将 js 函数定义为顶级函数,可以使用window.functionName()或来调用functionName()


gei*_*ger 5

我认为您正在从库中寻找allowInterop函数dart:jshttps ://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());
}
Run Code Online (Sandbox Code Playgroud)