加载视图时如何 运行 SystemJs 模块
How to run SystemJs module when view loads
我有一个加载 javascript 模块的组件,该模块基于 Bootstrap.js 和 Jquery 自动为基于 H1 的页面构建 table 内容, H2,... headers。组件代码如下:
import { bindable, bindingMode, customElement, noView } from 'aurelia-framework';
@noView()
@customElement('scriptinjector')
export class ScriptInjector {
@bindable public url;
@bindable public isLocal;
@bindable public isAsync;
@bindable({ defaultBindingMode: bindingMode.oneWay }) protected scripttag;
private tagId = 'bootTOCscript';
public attached() {
if (this.url) {
this.scripttag = document.createElement('script');
if (this.isAsync) {
this.scripttag.async = true;
}
if (this.isLocal) {
System.import(this.url);
return;
} else {
this.scripttag.setAttribute('src', this.url);
}
document.body.appendChild(this.scripttag);
}
}
public detached() {
if (this.scripttag) {
this.scripttag.remove();
}
}
}
对于那些不熟悉 Aurelia 的人来说,这只是简单地使用 SystemJs 从我的 app-bundle 中加载 bootstrap-toc.js 模块:
<scriptinjector url="lib/bootstrap-toc.js" is-local.bind='true'></scriptinjector>
我的问题是,虽然这在我第一次加载视图时工作得很好,但随后的访问不会生成目录(table 的内容)。我已经检查过 Aurelia 实际上在每次加载视图时都在调用 System.Import,但似乎一旦模块被导入一次,它就再也不会被导入(包中的代码永远不会运行第二次) .
有谁知道我如何在 re-enter 视图时 unload/reload/reset/rerun 模块?
好的,经过几天的努力,我找到了一个可以接受的解决方案,它保留了 TOC 库的所有功能,并且需要尽可能少地更改骨架项目和目标库。忘记上面的脚本注入器。
在index.html中,进行如下操作:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Holdings Manager</title>
<!--The FontAwesome version is locked at 4.6.3 in the package.json file to keep this from breaking.-->
<link rel="stylesheet" href="jspm_packages/npm/font-awesome@4.6.3/css/font-awesome.min.css">
<link rel="stylesheet" href="styles/styles.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body aurelia-app="main" data-spy="scroll" data-target="#toc">
<div class="splash">
<div class="message">Holdings Manager</div>
<i class="fa fa-spinner fa-spin"></i>
</div>
<!-- The bluebird version is locked at 4.6.3 in the package.json file to keep this from breaking -->
<!-- We include bluebird to bypass Edge's very slow Native Promise implementation. The Edge team -->
<!-- has fixed the issues with their implementation with these fixes being distributed with the -->
<!-- Windows 10 Anniversary Update on 2 August 2016. Once that update has pushed out, you may -->
<!-- consider removing bluebird from your project and simply using native promises if you do -->
<!-- not need to support Internet Explorer. -->
<script src="jspm_packages/system.js"></script>
<script src="config.js"></script>
<script src="jspm_packages/npm/bluebird@3.4.1/js/browser/bluebird.min.js"></script>
<script src="jspm_packages/npm/jquery@2.2.4/dist/jquery.min.js"></script>
<script src="jspm_packages/github/twbs/bootstrap@3.3.7/js/bootstrap.min.js"></script>
<script>
System.import('core-js').then(function() {
return System.import('polymer/mutationobservers');
}).then(function() {
System.import('aurelia-bootstrapper');
}).then(function() {
System.import('lib/bootstrap-toc.js');
});
</script>
</body>
</html>
这是假设您已经使用 jspm 安装了 bootstrap(它引入了 jquery 作为依赖项)。这还假设您已将 javascript 库(您想要合并的库,在我的例子中是 bootstrap-toc)放在 src/lib 文件夹中,并且您有 configured your bundling包含源文件夹中的 js 文件。
接下来,如果您的库定义了一个自执行的匿名函数,您需要获取该代码并将其移动到要应用该库的视图模型的 'attached' 方法中。所以在这种情况下,我有一个 'help' 视图,其中包含一堆 sections/subsections,我希望为其生成 TOC,因此代码如下所示:
import { singleton } from 'aurelia-framework';
@singleton()
export class Help {
public attached() {
$('nav[data-toggle="toc"]').each((i, el) => {
const $nav = $(el);
window.Toc.init($nav);
});
}
}
上面 'attached' 方法中的代码是从 bootstrap-toc.js 文件中剪切和粘贴的,我删除了自执行匿名方法。
我尝试将 system.import 用于 jquery/bootstrap 库,但这导致部分 TOC 功能停止工作,我已经失去耐心去弄清楚为什么这些库会保留为脚本参考现在。
此外,当您构建项目时,您会遇到错误:
help.ts(7,7): error TS2304: Cannot find name '$'.
help.ts(9,16): error TS2339: Property 'Toc' does not exist on type 'Window'.
这些不会在运行时引起问题,因为 $ 和 Toc 都将在视图实例化之前定义。您可以使用此解决方案 .
解决这些构建错误
我有一个加载 javascript 模块的组件,该模块基于 Bootstrap.js 和 Jquery 自动为基于 H1 的页面构建 table 内容, H2,... headers。组件代码如下:
import { bindable, bindingMode, customElement, noView } from 'aurelia-framework';
@noView()
@customElement('scriptinjector')
export class ScriptInjector {
@bindable public url;
@bindable public isLocal;
@bindable public isAsync;
@bindable({ defaultBindingMode: bindingMode.oneWay }) protected scripttag;
private tagId = 'bootTOCscript';
public attached() {
if (this.url) {
this.scripttag = document.createElement('script');
if (this.isAsync) {
this.scripttag.async = true;
}
if (this.isLocal) {
System.import(this.url);
return;
} else {
this.scripttag.setAttribute('src', this.url);
}
document.body.appendChild(this.scripttag);
}
}
public detached() {
if (this.scripttag) {
this.scripttag.remove();
}
}
}
对于那些不熟悉 Aurelia 的人来说,这只是简单地使用 SystemJs 从我的 app-bundle 中加载 bootstrap-toc.js 模块:
<scriptinjector url="lib/bootstrap-toc.js" is-local.bind='true'></scriptinjector>
我的问题是,虽然这在我第一次加载视图时工作得很好,但随后的访问不会生成目录(table 的内容)。我已经检查过 Aurelia 实际上在每次加载视图时都在调用 System.Import,但似乎一旦模块被导入一次,它就再也不会被导入(包中的代码永远不会运行第二次) .
有谁知道我如何在 re-enter 视图时 unload/reload/reset/rerun 模块?
好的,经过几天的努力,我找到了一个可以接受的解决方案,它保留了 TOC 库的所有功能,并且需要尽可能少地更改骨架项目和目标库。忘记上面的脚本注入器。
在index.html中,进行如下操作:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Holdings Manager</title>
<!--The FontAwesome version is locked at 4.6.3 in the package.json file to keep this from breaking.-->
<link rel="stylesheet" href="jspm_packages/npm/font-awesome@4.6.3/css/font-awesome.min.css">
<link rel="stylesheet" href="styles/styles.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body aurelia-app="main" data-spy="scroll" data-target="#toc">
<div class="splash">
<div class="message">Holdings Manager</div>
<i class="fa fa-spinner fa-spin"></i>
</div>
<!-- The bluebird version is locked at 4.6.3 in the package.json file to keep this from breaking -->
<!-- We include bluebird to bypass Edge's very slow Native Promise implementation. The Edge team -->
<!-- has fixed the issues with their implementation with these fixes being distributed with the -->
<!-- Windows 10 Anniversary Update on 2 August 2016. Once that update has pushed out, you may -->
<!-- consider removing bluebird from your project and simply using native promises if you do -->
<!-- not need to support Internet Explorer. -->
<script src="jspm_packages/system.js"></script>
<script src="config.js"></script>
<script src="jspm_packages/npm/bluebird@3.4.1/js/browser/bluebird.min.js"></script>
<script src="jspm_packages/npm/jquery@2.2.4/dist/jquery.min.js"></script>
<script src="jspm_packages/github/twbs/bootstrap@3.3.7/js/bootstrap.min.js"></script>
<script>
System.import('core-js').then(function() {
return System.import('polymer/mutationobservers');
}).then(function() {
System.import('aurelia-bootstrapper');
}).then(function() {
System.import('lib/bootstrap-toc.js');
});
</script>
</body>
</html>
这是假设您已经使用 jspm 安装了 bootstrap(它引入了 jquery 作为依赖项)。这还假设您已将 javascript 库(您想要合并的库,在我的例子中是 bootstrap-toc)放在 src/lib 文件夹中,并且您有 configured your bundling包含源文件夹中的 js 文件。
接下来,如果您的库定义了一个自执行的匿名函数,您需要获取该代码并将其移动到要应用该库的视图模型的 'attached' 方法中。所以在这种情况下,我有一个 'help' 视图,其中包含一堆 sections/subsections,我希望为其生成 TOC,因此代码如下所示:
import { singleton } from 'aurelia-framework';
@singleton()
export class Help {
public attached() {
$('nav[data-toggle="toc"]').each((i, el) => {
const $nav = $(el);
window.Toc.init($nav);
});
}
}
上面 'attached' 方法中的代码是从 bootstrap-toc.js 文件中剪切和粘贴的,我删除了自执行匿名方法。
我尝试将 system.import 用于 jquery/bootstrap 库,但这导致部分 TOC 功能停止工作,我已经失去耐心去弄清楚为什么这些库会保留为脚本参考现在。
此外,当您构建项目时,您会遇到错误:
help.ts(7,7): error TS2304: Cannot find name '$'.
help.ts(9,16): error TS2339: Property 'Toc' does not exist on type 'Window'.
这些不会在运行时引起问题,因为 $ 和 Toc 都将在视图实例化之前定义。您可以使用此解决方案