最佳 Alpine.js 替代方案
在本文中,我将向您介绍 Alpine.js 的绝佳替代品,它将帮助您使用服务器端 HTML 完成相同的操作(甚至更多)。
几个月前,我写了一篇有关 HTMX 的类似文章,现在我终于可以写一下使用HMPL而不是Alpine.js可以获得的好处。
我认为这个想法比迄今为止所做的有更大的潜力。
好吧,让我们开始吧!
👀 我们如何比较?
首先,所有比较都将在服务器连接的上下文中进行。我们不会在这里考虑常规客户端功能的选项。尽管一切都在客户端完成,但仍然存在明显的差异。
比较时我们将考虑以下参数:
- 渲染
- 自定义服务器请求
- 磁盘空间
- 模块内部是什么样的
我们还将讨论支持、安装简易性和其他一些要点。
🔧 渲染
在现代 Web 开发中,界面渲染方法的选择至关重要。我们将探讨两种截然不同的方法:HMPL 中的模板编译和 Alpine.js 的声明式方法。这两种技术为用户界面提供了不同的处理范例,每种范例都有各自的优势和实现特性。
HMPL
HMPL 使用客户端模板编译,这意味着标记被转换成动态生成 HTML 的 JavaScript 函数。
const templateFn = hmpl.compile(`
  <div>
    {{#request 
       src="/api/my-component"   
       indicators=[
         {
            trigger: "pending"
            content: "<p>Loading...</p>"
         }
       ]}}
    {{/request}}
  </div>
`);
// Usage
const component = templateFn();
该模板被编译一次为可执行函数,该函数:
- 
  创建优化的渲染函数 
- 
  缓存结果以供重复使用 
- 
  为将来的更新准备 DOM 结构 
Alpine.js
Alpine.js 提供了一种声明式风格——您可以通过属性( x-data、、 )直接在 HTML 中描述行为。x-showx-text
<div x-data="{ user: null, loading: true }"
     x-init="fetch('/api/user')
       .then(r => r.json())
       .then(data => { user = data; loading = false; })">
  <template x-if="loading">
    <div>Loading...</div>
  </template>
  <div x-show="user" class="user-card">
    <h2 x-text="user.name"></h2>
    <span x-show="user.isPremium" class="badge">Premium</span>
  </div>
</div>
以下是 Alpine.js 代码工作原理的简明 4 点细分:
- 
  该组件使用 Alpine.js 指令直接在 HTML 标记中定义其反应状态和数据获取逻辑。 
- 
  该 x-init钩子在组件安装时自动触发数据加载,管理请求和状态更新。
- 
  Alpine 的 x-if指令x-show根据加载状态和数据可用性处理动态 UI 渲染。
- 
  当状态改变时,模板会自动重新渲染,使 UI 与底层数据保持同步,而无需手动操作 DOM。 
比较
HMPL 提供了一种自动化渲染方法,内置了请求处理和模板功能,非常适合需要编译的复杂数据驱动组件。Alpine.js 通过显式 fetch 调用和响应式状态管理提供了更透明的控制,更适合轻量级交互。具体选择取决于项目需求——HMPL 擅长结构化模板,而 Alpine.js 则擅长快速原型设计和简单的动态元素。
🪄 自定义服务器请求
在构建动态 Web 应用程序时,高效地管理服务器请求至关重要。与自定义范围有限的 HTMX 不同,Alpine.js 提供了更广泛的自定义范围,自定义过程本身几乎与 jsx 类似,只需将 js 代码直接插入属性即可。当然,唯一的限制是模板。
<div x-data="{ user: null, error: null }"
     x-init="fetch('/api/user')
       .then(r => r.json())
       .then(data => user = data)
       .catch(e => error = e)">
</div>
用这种方法我们看到它非常方便,但问题是它很可能看起来像eval,或者根据现成的模式处理模板。
这种方法存在许多严重的缺陷,因为随着 JS 的每个新版本的发布,越来越多的新功能需要通过这种方法来支持。在 jsx 中,这一点是合理的,因为事实上,jsx 是 React 的基础,而在这里它只是一个可以通过script标签连接的模块。我们严重依赖于版本更新,这使得这种方法虽然方便,但并不完全实用。
在 HMPL 中,使用了一种不同的方法,我们可以直接在模板中编写我们需要的一些最小部分,例如方法、接收 HTML 的路由和其他内容,但是我们将整个 js 部分写入 js 中。
const templateFn = hmpl.compile(...);
const elementObj = templateFn(({
  request: { event, clearInterval }
})=>{
  clearInterval?.();
  return {
      mode: "cors",
      cache: "no-cache",
      credentials: "same-origin",
      headers: {
        "Content-Type": "text/html",
      },
      redirect: "follow",
      get: (prop, value) => {},
      referrerPolicy: "no-referrer",
      body: new FormatData(event.target, event.submitter),
    }
});
这里,js 部分和 html 部分有明确的区分。因此,你不会依赖于模块的新版本,因为描述 js 所需的一切,你都可以在这里编写,即使是 1.0.0 版本,即使是 3.0.1 版本。
此外,在 Alpine.js 中,使用此类语法存在 XSS 注入的风险。没错,它当然不是真正的eval,而是相同的,只是语法有限,可以避免大多数风险,但仍然存在风险。这不仅是 Alpine.js 的问题,也是所有模块(包括 HMPL)的问题。顺便说一下,HMPL 中有一个选项,可以从sanitize传入 HTML DOMPurify。
📁 磁盘空间
这可能是比较时最简单、最易理解的事情。只需编写相同的代码并进行比较(但我们必须明白,如果应用程序很大,那么代码也会呈指数级增长)。
Alpine.js
document.querySelector(
  "#app"
).innerHTML = `<div x-data="{ count: 0, l() { fetch('/a').then(r => r.text()).then(d => this.c = d)}}"><button @click="l()">Click!</button><div>Clicks: <span x-text="c"></span></div></div>`;
HMPL
document
  .querySelector("#app")
  .append(
    hmpl.compile(
      `<div><button>Click!</button><div>Clicks: {{#r src= "/api/clicks" after="click:button" }}{{/r}}</div></div>`
    )().response
  );
这里大概是清楚了,写出来会比较短。
但是,如果您仍然需要完整的测试,那么有一个包含 tests 的存储库。该模块还有第二个版本,它更短,但第三个版本的本质没有改变。
这些数字最接近大型和小型项目的实际结果。
⚙️ 模块内部是啥
这是指发送请求本身的技术。我不会写关于RegExp处理模板的方法,或者如何将元素保存到数组中——这些对客户端来说根本不应该有趣。
我们主要考虑的是XMLHTTPRequest支持fetch。关于这个话题,我们有以下内容:
Alpine.js
fetchAlpine.js 与和方法完全兼容XMLHTTPRequest。在某些情况下,这允许发出更精确的请求,例如overrideMimeType:
<div x-data="{ data: null }"
     x-init="
       const xhr = new XMLHttpRequest();
       xhr.overrideMimeType("text/html");
       xhr.open('GET', '/api/data');
       xhr.onload = () => { data = JSON.parse(xhr.responseText) };
       xhr.send();
     ">
  <div x-text="data?.message || 'Loading...'"></div>
</div>
尽管这种方法存在缺点eval,但它仍然是一种非常方便的切换方式,Alpine.js 在这方面可以发挥一定的优势。在相同的 HTMX 中,您只能使用它,XMLHTTPRequest而无法更改它。
HMPL
不幸的是(或者说幸运的是),HMPL 不支持XMLHTTPRequest请求,并且所有内容都建立在 之上fetch,这是不可替代的。请求发生在模块内部,您只需描述它们:
<div>
    <button data-action="increment" id="btn">Click!</button>
    <div>Clicks: {{#request
      src="/api/clicks"
      after="click:#btn"
    }}{{/request}}</div>
</div>
这也有一个优点,因为then,catch和其他东西都是在模块内实现的,所以你不必像在 jsx 中那样编写它。
结论
当然,你可以在项目中使用最适合你的框架。比如说,在文章中我们讨论了与服务器请求相关的部分,但 Alpine.js 也包含其他部分,这使得它成为一种轻量级框架。但是,如果我们要处理服务器端的工作,我建议(谁会怀疑呢👽)使用 HMPL,因为它更适合这项任务。所以,这两个选项都很不错!
🔗 模块链接:
HMPL - https://github.com/hmpl-language/hmpl
 Alpine.js - https://github.com/alpinejs/alpine
非常感谢大家阅读这篇文章!
文章来源:https://dev.to/hmpljs/best-alpinejs-alternative-2hme 后端开发教程 - Java、Spring Boot 实战 - msg200.com
            后端开发教程 - Java、Spring Boot 实战 - msg200.com
          
