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

对于 Webview 相关功能,我使用方法通道通过原生 Android 和 iOS 代码打开 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 方法。

【问题讨论】:

    标签: javascript flutter flutter-web


    【解决方案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);
    }
    

    调试步骤

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-19
      • 2020-01-22
      • 1970-01-01
      • 2020-04-03
      • 2023-04-05
      • 2019-03-04
      • 2020-04-22
      相关资源
      最近更新 更多