【问题标题】:is it possible to lazily use JS libs with Dart?是否可以在 Dart 中懒惰地使用 JS 库?
【发布时间】:2019-08-02 10:20:59
【问题描述】:

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

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

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

【问题讨论】:

  • 我有在初始化角度组件期间加载 js-library 的经验。 github.com/alexd1971/angular_grecaptcha/blob/master/lib/src/… 在 ngOnInit 脚本标签中创建并添加到 DOM。在 ngAfterViewInit 中等待脚本被加载并初始化组件。但不幸的是,这并不总是有效。例如这里:github.com/alexd1971/angular_flatpickr。我还没找到原因。
  • 听起来像是等待加载完成的问题。我不久前使用过这种方法,它对我有用(虽然不是 Chartjs)
  • 我尝试在 main.dart 上加载脚本以确保它已加载,但仍然没有工作
  • 问题是dart加载后某些JS文件无法添加到dom中。刚刚通过在 main.dart.js 脚本后简单添加 <script src=chartjs></script> 对其进行了测试,它抛出了这个错误:Error: Mismatched anonymous define() module: function(){var define,module,exports;

标签: dart dart-2


【解决方案1】:

这是 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];
    }
}

【讨论】:

    【解决方案2】:

    找到了更好的方法!

    让我们在 dart 加载后删除 define 变量,然后任何第三方库在添加异步时都可以工作: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>
    

    【讨论】:

      【解决方案3】:

      你可以试试deferred as语法:

      import 'package:chartjs/chartjs.dart' deferred as chartjs;
      
      void main() {
          chartjs.loadLibrary().then(() { ... });
      }
      

      【讨论】:

      • 但这会使界面延迟,而不是实际的 js 脚本,对吧?
      猜你喜欢
      • 2017-01-13
      • 1970-01-01
      • 2019-09-17
      • 1970-01-01
      • 2016-05-12
      • 1970-01-01
      • 2019-04-19
      • 1970-01-01
      • 2022-12-25
      相关资源
      最近更新 更多