是否可以懒惰地将 JS 库与 Dart 一起使用?
is it possible to lazily use JS libs with Dart?
我正在使用 chartjs(使用 dart 接口 https://pub.dartlang.org/packages/chartjs)并试图通过将 <script src="chartjs.js"></script>
注入头部部分并等待它的加载事件来使用库来延迟它。
我收到此异常:无法读取未定义的 属性 'Chart'。
当脚本位于 dart 之前的 html 头部时不会发生。
那么,Dart加载后是否可以加载一个JS库?
您可以尝试 deferred as
语法:
import 'package:chartjs/chartjs.dart' deferred as chartjs;
void main() {
chartjs.loadLibrary().then(() { ... });
}
这是 DDC 中的一个问题。
它将 require.js 添加到 HTML 并与其他库冲突。
https://github.com/dart-lang/sdk/issues/33979
我找到的解决方案是从您要使用的 third-party 库中手动删除使用 requirejs 的 header 部分。
以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];
}
}
找到更好的方法了!
让我们在 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>
我正在使用 chartjs(使用 dart 接口 https://pub.dartlang.org/packages/chartjs)并试图通过将 <script src="chartjs.js"></script>
注入头部部分并等待它的加载事件来使用库来延迟它。
我收到此异常:无法读取未定义的 属性 'Chart'。
当脚本位于 dart 之前的 html 头部时不会发生。
那么,Dart加载后是否可以加载一个JS库?
您可以尝试 deferred as
语法:
import 'package:chartjs/chartjs.dart' deferred as chartjs;
void main() {
chartjs.loadLibrary().then(() { ... });
}
这是 DDC 中的一个问题。
它将 require.js 添加到 HTML 并与其他库冲突。
https://github.com/dart-lang/sdk/issues/33979
我找到的解决方案是从您要使用的 third-party 库中手动删除使用 requirejs 的 header 部分。
以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];
}
}
找到更好的方法了!
让我们在 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>