4

我正在使用 chartjs(使用 dart 接口https://pub.dartlang.org/packages/chartjs)并尝试通过将 a<script src="chartjs.js"></script>注入 head 部分并等待它的加载事件然后使用 lib 来推迟它。
我收到此异常:无法读取未定义的属性“图表”。

当脚本位于 dart 之前的 html 头部时,不会发生这种情况。

那么,是否可以在加载 Dart 后加载 JS lib?

4

3 回答 3

2

这是 DDC 中的一个问题。它将 require.js 添加到 HTML 并与其他库发生冲突。
https://github.com/dart-lang/sdk/issues/33979

我找到的解决方案是从您要使用的第三方库中手动删除使用 requirejs 的标头部分。

以chartjs为例:https ://cdn.jsdelivr.net/npm/chart.js@2.8.0/dist/Chart.js

您删除这两行:

typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(function() { try { return require('moment'); } catch(e) { } }()) :
typeof define === 'function' && define.amd ? define(['require'], function(require) { return factory(function() { try { return require('moment'); } catch(e) { } }()); }) :

然后可以将文件延迟添加到 DOM 中而不会发生冲突。

这是我懒惰地获取脚本的代码:

class ClientUtils {
    static final _scriptFetched = <String, Future<bool>>{};

    static ScriptElement _scr(String url) => new ScriptElement()
      ..async = true
      ..type = 'text/javascript'
      ..src = url;

    static Future<bool> fetchScript(String url,
            {String contextCheck}) async {
        bool shouldCheck = contextCheck?.isNotEmpty == true;

        hasContext() => js.context.hasProperty(contextCheck) &&
                    js.context[contextCheck] != null;

        if (shouldCheck && hasContext())
            return true;

        if (!_scriptFetched.containsKey(url)) {
            Completer<bool> c = new Completer<bool>();

            if (!shouldCheck) {
                ScriptElement s = _scr(url)
                    ..onLoad.forEach((Event e) {
                        c.complete(true);
                    });

                document.body.children.add(s);
            } else {
                Timer.periodic(Duration(milliseconds: 300), (t) {
                    if (hasContext()) {
                        t.cancel();
                    }
                    c.complete(true);
                });

                document.body.children.add(_scr(url));
            }

            _scriptFetched[url] = c.future;
        }
        return _scriptFetched[url];
    }
}

于 2019-03-15T23:06:54.753 回答
2

找到了更好的方法!

让我们在 dart 加载后删除define变量,然后在添加 async 时任何第三方库都可以工作:D

将此添加到您的 main() 中:

import 'dart:js';

void main() {
  context.callMethod('fixRequireJs');
}

在你的 index.html 中:

    <script type="text/javascript">
      window.fixRequireJs = function()
      {
        console.log('define is ', typeof define);
        if (typeof define == 'function') {
          console.log('removing define...');
          delete define;
          window.define = null;
        }
      }
    </script>
于 2019-03-15T23:58:35.563 回答
0

您可以尝试以下deferred as语法:

import 'package:chartjs/chartjs.dart' deferred as chartjs;

void main() {
    chartjs.loadLibrary().then(() { ... });
}
于 2019-03-12T09:34:49.603 回答