视图加载时如何运行SystemJs模块 [英] How to run SystemJs module when view loads

查看:45
本文介绍了视图加载时如何运行SystemJs模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个组件,该组件加载在Bootstrap.js和Jquery上构建的javascript模块,以基于H1,H2,...标头自动为页面构建目录.组件代码如下:

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从我的应用程序捆绑包中加载bootstrap-toc.js模块:

<scriptinjector url="lib/bootstrap-toc.js" is-local.bind='true'></scriptinjector>

我的问题是,尽管当我第一次加载视图时这可以很好地工作,但是随后的访问不会生成目录(目录).我检查过Aurelia实际上是不是在每次加载视图时都调用System.Import,但是似乎一旦模块导入一次,就永远不会再次导入(捆绑中的代码永远不会再次运行)./p>

有人知道我重新进入视图后如何卸载/重新加载/重置/重新运行该模块吗?

解决方案

好吧,因此,经过几天的努力,我找到了一个可以接受的解决方案,该方案保留了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安装了引导程序(它引入了jquery作为依赖项).这还假设您已将javascript库(您要合并的JavaScript库,在我的情况下为bootstrap-toc)放在src/lib文件夹中,并且您具有

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都将在实例化视图之前定义.您可以使用此解决方案这里.

I have a component that loads a javascript module that builds on Bootstrap.js and Jquery to automatically build a table of contents for a page based on H1,H2,... headers. The component code is as follows:

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();
    }
  }
}

Essentially for those not familiar with Aurelia, this simply uses SystemJs to load the bootstrap-toc.js module from my app-bundle wherever I put this on my view:

<scriptinjector url="lib/bootstrap-toc.js" is-local.bind='true'></scriptinjector>

My problem is that although this works perfectly when I first load the view, subsequent visits don't generate a TOC (table of contents). I have checked that Aurelia is in fact calling System.Import each time the view is loaded, but it seems that once a module has been imported once, it is never imported again (the code from the bundle never runs a second time).

Does anyone know how I can unload/reload/reset/rerun the module when I re-enter the view?

解决方案

Ok, so after days of fighting with this I have figured out an acceptable solution that keeps all the functionality of the TOC library and requires as few changes to the skeleton project and the target library as I could manage. Forget the script injector above.

In the index.html, do as follows:

<!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>

This is assuming you have installed bootstrap using jspm (which brings in jquery as a dependency). This also assumes you have put the javascript library (the one you want to incorporate, bootstrap-toc in my case) in your src/lib folder and that you have configured your bundling to include js files from your source folder.

Next, if your library has a self executing anonymous function defined, you need to take that code and move it inside the 'attached' method of the viewmodel where you want the library to be applied. So in this case, I have a 'help' view with a bunch of sections/subsections that I wanted a TOC generated for, so the code looks like:

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);
      });
  }
}

The code inside the 'attached' method above was cut and pasted from the bootstrap-toc.js file and I removed the self-executing anonymous method.

I tried using system.import for the jquery/bootstrap libraries but that made part of the TOC functionality stop working and I have lost my patience to figure out why so those libraries are staying as script references for now.

Also, when you build the project you will get errors :

help.ts(7,7): error TS2304: Cannot find name '$'.
help.ts(9,16): error TS2339: Property 'Toc' does not exist on type 'Window'.

These do not cause problems at runtime since both $ and Toc will be defined before the view is ever instantiated. You can solve these build errors with this solution here.

这篇关于视图加载时如何运行SystemJs模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆