можно ли лениво использовать JS libs с Dart? - PullRequest
2 голосов
/ 12 марта 2019

Я использую chartjs (с интерфейсом dart https://pub.dartlang.org/packages/chartjs) и пытаюсь сделать его отложенным, введя <script src="chartjs.js"></script> в раздел head и ожидая события загрузки, чтобы затем использовать lib.
Я получаю это исключение: не могу прочитать свойство 'Chart' из неопределенного.

Этого не происходит, когда скрипт находится в заголовке html до запуска.

Итак, можно ли загрузить библиотеку JS после загрузки Dart?

Ответы [ 3 ]

1 голос
/ 16 марта 2019

это проблема в 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];
    }
}

1 голос
/ 16 марта 2019

нашел лучший способ!

позволяет удалить переменную 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>
0 голосов
/ 12 марта 2019

Вы можете попробовать синтаксис deferred as:

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

void main() {
    chartjs.loadLibrary().then(() { ... });
}
...