6

我们正在使用 Lit Element,我们的组件文件变得相当大,因为我们必须在 .js 文件中编写样式和 html。有没有办法将它们拆分为单独的文件,然后将它们导入到我们的组件中?这样做的最佳方法是什么?HTML 和 CSS 尤其使我们的工作流程变得困难,因为我们的文件变得过于臃肿。

更新:Supersharp 的建议帮助我将 CSS 和 html 模板分开,但我在将 html 模板与指定属性绑定时遇到问题。我有一个服务文件,它正在对我指定的文件发出 XML 请求,我将它们导入到我的组件文件中。这是我的组件:

import { LitElement, html} from '@polymer/lit-element';

import HtmlLoader from './Service/HtmlLoader';

class TestAnimatedButtonElement extends LitElement {

  static get properties() {
    return {
      _text: {
        type: String
      }
    }
  }

  constructor() {
    super();
    this.htmlTemplate = HtmlLoader.prototype.getHtmlTemplate('/src/Components/ExampleElements/test-animated-button-element.html');
  }

  render(){
    this.htmlTemplate.then( template => this.shadowRoot.innerHTML = template)
    return html( [this.htmlTemplate] );
  }

  handleButton(e) {
    //e.preventDefault();
    console.log('Button pressed');
  }
}
customElements.define('test-animated-button-element', TestAnimatedButtonElement);

这是我的 html 文件:

<link rel="stylesheet" href="src/Components/animatedButton/animated-button-element.css"/>
<a href="#" class="btn btn--white btn--animated" @click="${(e) => this.handleButton(e)}">${this._text}</a>

这是我用来制作 XMLHttpRequest 的服务文件:

export default class HtmlLoader {

    xhrCall(url){
      return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open("GET", url);
        xhr.onload = () => resolve(xhr.responseText);
        xhr.onerror = () => reject(xhr.statusText);
        xhr.send();
      });
    }

    getHtmlTemplate(url) {
       return this.xhrCall(url);
    }

}
4

2 回答 2

3

这是 ES Modules 的缺点,这也是为什么尽管其他浏览器供应商对 HTML Imports 不屑一顾,Google 却长期推动 HTML Imports。

您可以分离出您的 CSS 和 JS,但如果您在运行时获取它们,您将向浏览器添加额外的往返行程。特别是你的模板是异步检索的,如果你等待它们,你会阻塞主 JS 线程,如果你这样做,await你会中断lit-element,因为它期望根模板是同步的。

可以(但不应该)使用until

import { until } from 'lit-html/directives/until';

...

render(){
    return html`until(
        this.loadTemplate(
            '/src/Components/ExampleElements/test-animated-button-element.html',
            this.foo, 
            this.bar), html`Loading...`)`;
}

async loadTemplate(path, ...parts) {
    // You're using templates you can use fetch, instead of XMLHttpRequest
    const r = await fetch(path, { method: 'GET', credentials: 'same-origin' });
    if(r.ok)
         return html(await r.text(), parts);

    return html`Not Found: ${path}`
}

但是,我注意到您使用的是裸模块(即.在开头和.js结尾都没有 a),因此您不能将此文件直接提供给浏览器(目前还没有一个可以处理裸模块)。简而言之:你必须有一些东西:

import { LitElement, html} from '@polymer/lit-element';

进入:

import { LitElement, html } from '../../node_modules/@polymer/lit-element/lit-element.js';

或者将它们捆绑到一个文件中。鉴于您正在这样做,为什么不在构建时让您的捆绑器(Webpack、RollupJS、Browserify 等)将您的 CSS 和 HTML 导入文件中?

最后,使用这些解决方案中的任何一个,您都会失去写时部分<-> html 关系,这对 CSS 无关紧要,但会使 HTML 部分更难开发/维护。使用像 lit 这样的库,您希望在 JS 中使用 HTML,原因与 JSX/React/Preact 运行良好的原因相同。如果您的文件太大,那么我认为解决方案不是通过 JS/CSS/HTML 拆分它们 - 而是将它们拆分为更多组件。

所以,例如,假设你有一个巨大的<product-detail>控制...

  • 产品详细信息.js
  • 产品详细信息.html
  • 产品详细信息.css

  • 产品详细信息.js
  • 产品细节dimensions.js
  • 产品详细信息specs.js
  • 产品详细信息parts.js
  • 产品详细信息preview.js
  • ETC

分解每个组件以执行特定任务。的重点lit-element是使所有这些尽可能简单地创建,并且您需要许多小的、独立的组件。

于 2018-12-13T09:18:12.973 回答
1

您可以分别导入 CSS 和 HTML 部分。

CSS

在 HTML 代码中使用<link rel="stylesheet">元素。

HTML

您可以使用 HTML Imports(已弃用)、XMLHttpRequest 或 fetch(),正如这篇关于为自定义元素导入模板的文章中所解释的那样。

更新

XMLHtpRequest你会在 Promise 中得到答案。

render(){
    this.htmlTemplate.then( template =>
        this.shadowRoot.innerHTML = template
    )
}
于 2018-11-29T16:48:13.407 回答