【问题标题】:Load Local Javascript file In Flutter在 Flutter 中加载本地 Javascript 文件
【发布时间】:2021-03-25 12:44:12
【问题描述】:

我有一个 Flutter 项目,我正在使用 webview_flutter 包创建一个 Webview 小部件。

这是我的 ma​​in.dart 文件:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Communication Bridge',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Native - JS Communication Bridge'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  WebViewController _controller;
  final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(title: Text('Webview')),
      body: WebView(
        initialUrl: 'about:blank',
        javascriptMode: JavascriptMode.unrestricted,
        javascriptChannels: Set.from([
          JavascriptChannel(
              name: 'messageHandler',
              onMessageReceived: (JavascriptMessage message) {
                _scaffoldKey.currentState.showSnackBar(
                    SnackBar(
                        content: Text(
                            message.message)
                    )
                );
              })
        ]),
        onWebViewCreated: (WebViewController webviewController) {
          _controller = webviewController;
          _loadHtmlFromAssets();
        },
      ),
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.arrow_upward),
        onPressed: () {
          _controller.evaluateJavascript('foo("message")');
        },
      ),
    );

  }

  _loadHtmlFromAssets() async {
    String file = await rootBundle.loadString('assets/index.html');
    _controller.loadUrl(Uri.dataFromString(
        file,
        mimeType: 'text/html',
        encoding: Encoding.getByName('utf-8')).toString());
  }

}

如您所见,我正在将一个本地 html 文件加载到 webview (_loadHtmlFromAssets) 中。

html 文件有以下标记:

   <html>

    <head>
        <title>My Local HTML File</title>
    </head>

    <body>
        <script type="text/javascript">
            function foo(msg) {
               //Code
            }
        </script>
    </body>
</html>

当 html 包含像上面代码这样的 javascript 时,我没有问题并且能够从应用程序与 webview 进行通信。

我想将 javascript 代码放在一个单独的文件中,而不是放在 html 文件中。

 <html>
    
        <head>
            <title>My Local HTML File</title>
        </head>
    
        <body>
            <script src="script.js"></script> // <-------
        </body>
    </html>

当我尝试这样做时,我收到以下错误(它试图引用 javascript 文件中定义的方法):

I/chromium(15188): [INFO:CONSOLE(1)] "Uncaught ReferenceError: foo is not defined

我已在资产下的 pubspec.yaml 中添加了该文件,所以这不是问题。

我在 SO 上看到过这个 question,但那里的解决方案没有帮助。

【问题讨论】:

    标签: flutter dart webview


    【解决方案1】:

    您可以在下面复制粘贴运行4完整代码main.dart, index.html, script.js, style.css
    并在AndroidManifest.xml 中添加android:usesCleartextTraffic="true"
    您可以使用包https://pub.dev/packages/webview_flutter_plus
    webview_flutter_pluswebview_flutter 的强大扩展。这个包有助于从AssetsStrings 加载本地HTML, CSSJavascript 内容。这继承了 webview_flutter 的所有功能,并进行了少量 API 更改。

    您可以直接从https://github.com/shah-xad/webview_flutter_plus下载完整的示例代码并进行测试

    代码sn-p

    WebViewPlus(
          initialUrl: 'assets/index.html',
          onWebViewCreated: (controller) {
            this._controller = controller;
          },
          onPageFinished: (url) {
            _controller.getHeight().then((double height) {
              print("Height: " + height.toString());
              setState(() {
                _height = height;
              });
            });
          },
          javascriptMode: JavascriptMode.unrestricted,
        ),
    

    assets的设置

    示例代码的工作演示

    main.dart的完整代码

    import 'package:flutter/material.dart';
    import 'package:webview_flutter_plus/webview_flutter_plus.dart';
    
    void main() {
      runApp(WebViewPlusExample());
    }
    
    class WebViewPlusExample extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: WebViewPlusExampleMainPage(),
        );
      }
    }
    
    class WebViewPlusExampleMainPage extends StatefulWidget {
      @override
      _WebViewPlusExampleMainPageState createState() =>
          _WebViewPlusExampleMainPageState();
    }
    
    class _WebViewPlusExampleMainPageState
        extends State<WebViewPlusExampleMainPage> {
      WebViewPlusController _controller;
      double _height = 1000;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('webview_flutter_plus Example'),
          ),
          body: ListView(
            children: [
              SizedBox(
                height: 500,
                child: WebViewPlus(
                  initialUrl: 'assets/index.html',
                  onWebViewCreated: (controller) {
                    this._controller = controller;
                  },
                  onPageFinished: (url) {
                    _controller.getHeight().then((double height) {
                      print("Height: " + height.toString());
                      setState(() {
                        _height = height;
                      });
                    });
                  },
                  javascriptMode: JavascriptMode.unrestricted,
                ),
              )
            ],
          ),
        );
      }
    }
    

    index.html的完整代码

    <!DOCTYPE HTML>
    <html>
    <head>
        <title>webview_flutter_plus</title>
        <link crossorigin="anonymous" href="style.css" rel="stylesheet">
    </head>
    <body>
    <div id="testDiv">
        webview_flutter_plus is an extension of webview_flutter to load HTML, CSS and Javascript even from Assets or String.
        <br>
        <br>
        <br>
        Please tap the text to see Javascript execution.
    </div>
    <script src="script.js"></script>
    </body>
    

    script.js的完整代码

    var testDiv = document.getElementById("testDiv");
    testDiv.addEventListener('click', function f(e) {
        testDiv.setAttribute('style', 'background:red;')
        console.log("style changed");
    })
    

    style.css的完整代码

    #testDiv {
        background: green;
        color: white;
    }
    

    【讨论】:

    • 感谢您的回答。你是说我问的场景不能使用 webview_flutter 包吗?
    • 其实有个pull requestgithub.com/flutter/plugins/pull/1247,很久以前,还没合并。
    • 如果你有截止日期,我建议你可以使用这个扩展。因为它继承了 webview_flutter 的所有功能,并进行了细微的 API 更改
    猜你喜欢
    • 2020-10-15
    • 2020-04-17
    • 2022-10-17
    • 2011-04-23
    • 2021-11-02
    • 1970-01-01
    • 2013-10-05
    • 1970-01-01
    • 2015-12-02
    相关资源
    最近更新 更多