Aurelia:样式表已加载但未删除

时间:2018-03-05 18:58:55

标签: css aurelia

在aurelia项目中,我有几个组件可以导入其他样式表,例如来自语义ui。离开组件页面后,样式表仍处于活动状态,不会被删除。是否有可能卸载'样式表?

2 个答案:

答案 0 :(得分:1)

更新(2018-03-27):

我提交了一个PR以启用此选项,您可以在此处跟踪:https://github.com/aurelia/templating-resources/pull/344

原始答案:

一句警告,这是未经测试的,而且是aurelia-internals-hacky。

所能做的是覆盖默认的CSSViewEngineHooksCSSResource类,以跟踪它注入的样式元素,然后添加beforeUnbind个钩子再次删除样式..在unbind之前(在分离之后)

不幸的是,CSSResource类不是从aurelia-templating-resources导出的,所以我们需要更深层地覆盖一层并覆盖返回CSSResource实例的现有样式加载器插件。

以下是:

首先我们从aurelia-templating-resources/src/css-resource.js获取代码,将其放入我们自己的src/css-resource.js/ts并对其进行一些调整(不要过多考虑它的大小,它是' s只是一个带有一些小调整的复制粘贴,注释注释):

import {ViewResources, resource, ViewCompileInstruction} from 'aurelia-templating';
import {Loader} from 'aurelia-loader';
import {Container} from 'aurelia-dependency-injection';
import {relativeToFile} from 'aurelia-path';
import {DOM, FEATURE} from 'aurelia-pal';

let cssUrlMatcher = /url\((?!['"]data)([^)]+)\)/gi;

function fixupCSSUrls(address, css) {
  if (typeof css !== 'string') {
    throw new Error(`Failed loading required CSS file: ${address}`);
  }
  return css.replace(cssUrlMatcher, (match, p1) => {
    let quote = p1.charAt(0);
    if (quote === '\'' || quote === '"') {
      p1 = p1.substr(1, p1.length - 2);
    }
    return 'url(\'' + relativeToFile(p1, address) + '\')';
  });
}

class CSSResource {
  constructor(address: string) {
    this.address = address;
    this._scoped = null;
    this._global = false;
    this._alreadyGloballyInjected = false;
  }

  initialize(container: Container, target: Function): void {
    this._scoped = new target(this);
  }

  register(registry: ViewResources, name?: string): void {
    if (name === 'scoped') {
      registry.registerViewEngineHooks(this._scoped);
    } else {
      this._global = true;
    }
  }

  load(container: Container): Promise<CSSResource> {
    return container.get(Loader)
      .loadText(this.address)
      .catch(err => null)
      .then(text => {
        text = fixupCSSUrls(this.address, text);
        this._scoped.css = text;
        if (this._global) {
          this._alreadyGloballyInjected = true;
          // DOM.injectStyles(text); <- replace this
          // this is one of the two possible moments where the style is injected
          // _scoped is the CSSViewEngineHooks instance, and we handle the removal there
          this._scoped.styleNode = DOM.injectStyles(text);
        }
      });
  }
}

class CSSViewEngineHooks {
  constructor(owner: CSSResource) {
    this.owner = owner;
    this.css = null;
  }

  beforeCompile(content: DocumentFragment, resources: ViewResources, instruction: ViewCompileInstruction): void {
    if (instruction.targetShadowDOM) {
      DOM.injectStyles(this.css, content, true);
    } else if (FEATURE.scopedCSS) {
      let styleNode = DOM.injectStyles(this.css, content, true);
      styleNode.setAttribute('scoped', 'scoped');
    } else if (this._global && !this.owner._alreadyGloballyInjected) {
      // DOM.injectStyles(this.css); <- replace this
      // save a reference to the node so we can easily remove it later
      this.styleNode = DOM.injectStyles(this.css);
      this.owner._alreadyGloballyInjected = true;
    }
  }

  // this is the hook we add, here we remove the node again
  beforeUnbind(): void {
    if (this._global && this.owner._alreadyGloballyInjected) {
      DOM.removeNode(this.styleNode);
      this.owner._alreadyGloballyInjected = false;
    }
  }
}

export function _createCSSResource(address: string): Function {
  @resource(new CSSResource(address))
  class ViewCSS extends CSSViewEngineHooks {}
  return ViewCSS;
}

然后,在main.ts/js aurelia-templating-resources.js我们做同样的事情aurelia.use.standardConfiguration(),但我们自己的版本。 所以我们在<{>}之后执行 来覆盖现有的

let viewEngine = config.container.get(ViewEngine);
let styleResourcePlugin = {
  fetch(address) {
    return { [address]: _createCSSResource(address) };
  }
};
['.css', '.less', '.sass', '.scss', '.styl'].forEach(ext => viewEngine.addResourcePlugin(ext, styleResourcePlugin));

这应该可以解决问题.. :)

答案 1 :(得分:0)

我找到了解决此问题的插件: https://kuba-halle.de/tickets

但是对于最新的Webpack webpack.config.js,应该与插件自述文件有所不同。

您应该通过以下方式加载.css文件:

   use: [
          { loader: 'style-loader', options: { injectType: 'lazyStyleTag' } },
          'css-loader'
        ]

代替此:

  use: ['style-loader/useable', 'css-loader']