import - 将 HTML 和 CSS 与 Javascript Lit 元素分离

标签 import module web-component lit-html

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

更新:Supersharp 的建议帮助我分离了 CSS 和 html 模板,但我在将 html 模板与指定属性绑定(bind)时遇到问题。我有一个服务文件,它对我指定的文件发出 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);
    }
}

最佳答案

这就是 ES 模块的缺点,这就是为什么 Google 长期以来一直在插入 HTML 导入,尽管其他浏览器供应商极力反对。

您可以将 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 ),因此您无法将此文件直接提供给浏览器(没有浏览器可以处理裸模块)然而)。简而言之:你必须拥有一些可以改变的东西:

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

进入:

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

或者将它们捆绑到一个文件中。既然您正在这样做,为什么不让您的 bundler (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
  • 等等

分解每个组件来完成特定的任务。整点lit-element就是让所有这些的创建尽可能简单,并且您需要大量小型的、独立的组件。

关于import - 将 HTML 和 CSS 与 Javascript Lit 元素分离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53541349/

相关文章:

javascript - 两个Web组件之间的绑定(bind): Google map + geo-localisation

php - 开发 PHP 数据导入框架的最佳实践是什么?

php - Codeigniter 需要从一个模块连接到另一个模块

python - 我可以在模块中使用程序中创建的对象吗?

javascript - requirejs 具有揭示模块模式

dart - 用角 Dart 测试,范围为空

mysql - 错误代码 : 1148. 此 MySQL 版本不允许使用的命令

mysql - Magento 导入 "please wait"-> 导入完成而不通知

ruby-on-rails - 通过 http 而不是文件系统导入 SASS 部分

javascript - 自定义元素的属性可以驼峰式吗?