Lit简介:基于标准的反应库(反应标准的标杆是)

boyanx1天前技术教程1

  Lit基于Mozilla的Web组件标准,以提供简单、合规的反应前端。在一个技术替代品庞大的世界里,它可能会提供一条明确的前进道路。

  在用于被动编程的前端JavaScript框架中,Lit是一个有趣的选择。它引起了开发人员的相当大的兴趣,但与其他一些反应性框架相比,它仍然相对低调。Lit建立在Mozilla Web Components标准之上,优先考虑速度和一小套有用的功能。

  Mozilla Web组件标准

  要理解Lit,你必须了解Web组件。作为所有主要浏览器支持的浏览器标准,Web组件提供了定义UI组件的一致方法。Web组件的想法是在浏览器中为开发人员提供一套工具,以处理UI组件的普遍需求。在一个理想的世界里,每个框架——无论是React、Vue还是其他东西——都会位于Web组件层的顶部,为Web开发提供更多的一致性。

  Lit是一个干净、专注的库,它促进了开发人员使用Web组件的更舒适的体验。它通过生成网络组件来工作,这些组件只是自定义HTML元素。这些元素可以广泛使用,例如在React中。这是一个基于标准构建的简单问候组件:

  组件的工作原理和作用是显而易见的,尽管有几个有趣的功能,如构造函数和shadowRoot。主要需要注意的是,Web组件允许您使用浏览器标准定义封装功能,该标准可以直接在Web控制台中运行。

  使用Lit开发网络组件

  现在让我们来看看相同的功能,但使用Lit。

  此代码片段的目的与我们的Web组件示例相同,但您可以立即看到大小和复杂性已经减少。以@开头的装饰器(又名注释)让我们以简洁的方式声明customElement(这是Web组件最终所做的)和name属性。由于Lit的css函数(标记的模板字面函数),我们还删除了默认构造函数,不再需要CSS的内联标记。

  Lit还允许我们使用render方法来返回由html函数生成的模板。html函数参数的内容允许您将HTML与变量插值相结合。这与JSX和其他模板语法相似,但请注意,我们使用${}而不是{},并且我们用this来指代组件。

  尝试这个最简单的方法是使用Lit在线游乐场。请注意,在这个游乐场中,您需要使用TS(TypeScript)切换才能使注释工作。(此限制仅与游乐场有关;注释将与构建中的JavaScript配合使用。)

  为Lit组件增加反应性

  现在让我们在反应性方面迈出下一步,让Lit的name变量具有交互性。我们将添加一个输入,允许我们更改名称——aninput组件和模板中显示的名称之间的双向绑定。Lit让他们保持同步。

  以下代码仅包含已更改的有意义的部分:


render() {
    return html`
       <div>
         <input
          type="text" 
          .value=${this.name}     
          @input=${this._handleNameInput} 
          placeholder="Type a name..."
        />
         <p>Hello,  <span>${this.name} </span>! </p>
       </div>
    `;
  }

  _handleNameInput(event: Event) {
    const inputElement = event.target as HTMLInputElement;
    this.name = inputElement.value;
  }

  这里的功能与之前的示例相同,但现在我们有一个input元素和一个处理函数。输入是标准HTML类型文本。它也是一个标准值属性,但它的前缀是Lit的dot运算符。dot运算符将输入绑定到${this.name},这是使输入值对该变量反应的神奇成分。dot运算符告诉Lit,你想要值的实时JavaScript属性,而不是静态值。这确保了Lit将使输入保持最新,并对值进行任何编程更改。

  @input属性允许我们将更改处理程序指向我们的_handleNameInput 。该函数本身使用标准DOM操作来检索输入元素的值,然后将其分配给the.name变量。那是双向绑定的另一面。当用户更改输入中的值时,处理程序会更新this.name。Lit确保无论this.name 出现在哪里,它都会获得新的值。

  在 Lit 中使用内部组件状态

  所有反应库共同的另一个基本特征是内部组件状态。Lit还简化了反应编程的这一方面。例如,假设我们需要一个显示/隐藏功能。这将取决于纯粹的内部布尔值,因此不需要将其与与父属性或任何外部内容交互的属性连接起来。我们可以声明一个新的状态变量,如下所示:


  @state()
  private _showSecretMessage = false;

  现在,这将在用户界面中提供给我们。我们可以用它来切换一个部分的可见性:



${this._showSecretMessage
  ? html` <p class="conditional-text">This is the secret message! </p>`
  : '' /* Render nothing if false */
}

  This will go in the template, as part of the render function. It uses a template expression (the ${} construct) and within that, a JavaScript ternary operator (the ? : syntax). This will evaluate to the segment following the ? if this._showSecretMessage is true, or the part following : if it’s false. The net result is, if the value is true, we get a chunk of template HTML placed into the view at this point, and if not, we get nothing.

  这正是我们想要的——基于我们的切换的有条件渲染。为了实际切换值,我们可以添加一个按钮:


${this._showSecretMessage
  ? html` <p class="conditional-text">This is the secret message! </p>`
  : '' /* Render nothing if false */
}

  此按钮代码使用状态变量来有条件地显示适当的标签。以下是@click处理程序的外观:



_toggleSecretMessage() {
    this._showSecretMessage = !this._showSecretMessage;
}

  在这里,我们只是交换状态变量的值,Lit根据我们的三元显示来显示视图中的变化。现在,我们有一个可以展示和隐藏的面板。

  在Lit中渲染集合

  现在让我们来看看Lit渲染集合的能力。首先,我们将创建一个作为属性的Hobbits列表:


@property({ type: Array })
  hobbits = ["Frodo Baggins", "Samwise Gamgee", "Merry Brandybuck", "Pippin Took"];

  我们在这里使用属性而不是状态,因为我们可能会从父级设置此值。接下来,我们想展示我们的Hobbits:



 <h4>The Fellowship's Hobbits: </h4>
      ${this.hobbits && this.hobbits.length > 0
        ? html`
             <ul>
              ${this.hobbits.map(
                (hobbitName) => html` <li>${hobbitName} </li>`
              )}
             </ul>
          `
        : html` <p>(No hobbits listed in this roster!) </p>`
      }




  如果Hobbits是空的,我们再次使用三元条件运算符来显示消息。通过我们的默认数据,我们显示了最著名的霍比特人列表(除Bilbo外)。主要工作是通过在this.hobbits变量上使用map功能运算符来完成的。这让我们可以移动每个元素,并通过Lit的html函数输出适当的列表项目标记。

  使用Lit进行API调用

  现在让我们从中土世界切换到Westeros,并从远程API加载一些字符数据。

  首先,我们将创建一个内部state变量来管理获取承诺:



@state()
  private _characterDataPromise: Promise <unknown>;

  接下来,我们将实现一个constructor,因为在首次加载组件时,我们需要做一些事情。在这种情况下,我们正在加载数据:



constructor() {
    super();
    this._characterDataPromise = this._fetchCharacterData();
  }

  在这里,我们调用_fetchCharacterData函数:


private async _fetchCharacterData() {
  const apiUrl = "https://www.anapioficeandfire.com/api/characters?page=1&pageSize=10";

  try {
    const response = await fetch(apiUrl);

      if (!response.ok) {
        throw new Error(`API request failed with status: ${response.status}`);
      }

      const json: Array <{ name: string, culture: string, born: string, aliases: string[] }> = await response.json();

      if (json && json.length > 0) {
        const characterTemplates = json.map((char) => {
          const displayName = char.name || (char.aliases && char.aliases[0]) || "Unnamed Character";
          return html`
             <li>
               <strong>${displayName} </strong>
              ${char.culture ? html` <span class="character-details"> - Culture: ${char.culture} </span>` : ''}
              ${char.born ? html` <span class="character-details">, Born: ${char.born} </span>` : ''}
             </li>
          `;
        });
        return html` <ul>${characterTemplates} </ul>`;
      } else {
        return html` <p>No characters found in these lands! </p>`;
      }
    } catch (error) {
      console.error("Failed to fetch Game of Thrones character data:", error);
      return Promise.resolve(html` <p class="error-message">Could not summon characters: ${error.message} </p>`);
    }
  }

  这里的代码主要是标准JavaScript,除了我们使用Lit'shtml函数来为获取结果中的每个情况返回适当的模板标记。但请注意,实际的_fetchCharacterData函数返回一个承诺。在出现错误的情况下,它会明确这样做,但在所有情况下,异步函数都会返回一个承诺。另请注意,resolve方法是用html函数调用的内容调用的。

  我们在
this._characterDataPromise之前保存了这个承诺的句柄。保存的句柄让我们在主组件模板中智能地等待此调用的结果:


return html`
       <h4>Characters from the Seven Kingdoms (or thereabouts): </h4>
      ${until(
        this._characterDataPromise,
        html` <p class="loading-message">Sending a raven for news (loading characters...). </p>`
      )}
    `;




  再次,我们使用until()函数来等待承诺的最终结果。请注意,第二个参数显示等待的内容。

  结论

  Lit包含大量有趣的想法,其受欢迎程度并不奇怪,特别是考虑到其基于Web组件标准。最大的问题是,Lit是否会作为React、Svelte和Vue等一系列其他框架的通用组件系统起飞。如果是这样,我们将在相关性和采用方面进入一个全新的阶段。然而,就目前而言,Lit本身是一种可行的方法,对高度重视标准合规性的项目特别有吸引力。

相关文章

用了三年 Vue,我终于理解为什么“组件设计”才是重灾区

一开始写 Vue 的时候,谁不是觉得:“哇,组件好优雅!”三年后再回头一看,组件目录像垃圾堆,维护一处改三处,props 乱飞、事件满天飞,复用全靠 copy paste。于是我终于明白 —— 组件设...

在 .NET Core 中使用 SignalR 实现实时通信应用程序

概述:在现代 Web 开发环境中,对实时功能的需求越来越大。无论是实时聊天、实时通知还是动态仪表板,用户都希望获得即时更新。SignalR 是一个用于 ASP.NET 的库,可简化向应用程序添加实时...

工作中常用且容易遗忘的 CSS 样式清单整理(一)

为大家精心准备了工作中常用的CSS样式,都是自己工作中常用到的记录发,分享给大家,如果觉得可以希望点赞关注和评论。废话不多说先上图:最后把源码奉献给大家<!DOCTYPE html> &l...

react native使用ant design表单相互嵌套的问题

在React Native中使用Ant Design的Form组件进行表单提交时,如果在一个Form表单内嵌套了另一个Form表单,并且这两个表单位于父子组件之间,并且第二个嵌套的表单有一个提交按钮,...

前端面试模拟:常见的3个JavaScript经典考题

在一次备受期待的前端开发高级岗位面试中,你紧张地走进了会议室,对面坐着的是一位经验丰富的技术面试官。窗外阳光明媚,屋内却有一丝令人紧张的静谧。第一问:如何使用JavaScript实现事件委托?面试官微...

制作简易页面计算器的详细教程和代码分享

今天教大家一个比较简单实用的Web小应用:简单计算器。这个案例比较简单、比较直观,适合小孩或者初学编程者进行编程入门的练习。用html进行入门编程练习优点非常多:IDE框架比较轻,VSCode安装方便...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。