HTMX 实现数据加载时加载中动画

HTMX 实现数据加载时加载中动画

在前端开发中,因为网络延迟、后台数据处理等原因(特别是后台部署在 VPS、ECS 等云服务器时网络都会有延迟),用户的操作响应会有延迟,通常都会给出进度条、加载中等的提示告知用户系统在正常工作中。使用其它框架进行开发时都会有对应的组件,而且可以通过 JavaScript 进行控制。但使用 hx-get、hx-post 之类的 htmx 属性时,很多人就不知道该怎么触发这个加载中的状态了。

其实 htmx 已经提供了 hx-indicator 这样的操作特性,可以很方便地对加载中的状态进行展示及隐藏。

htmx 实现加载中的提示的原理就是通过 hx-indicator 属性指定一个元素, hx-indicator 的值是以 selector 的形式指定加载中提示的元素,hx-indicator 属性与 hx-get、hx-post 等操作放在同一个元素中,用户触发 hx-get 或 hx-post 等操作时,htmx 会往 hx-indicator 指定的元素中添加一个 htmx-request 类,操作接收到后台的响应后(200、400、500 等 http 响应码等效)会移除 htmx-request 类,这个类可以自行通过 CSS 进行覆盖。

例如以下的 CSS 代码:

/* 这个示例中 hx-indicator 只跟 opacity 属性有关 */
.loading {
  opacity: 0;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 50px;
  height: 50px;
  border: 4px solid #ccc;
  border-top: 4px solid #3498db;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

.htmx-request {
  opacity: 1;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }

  100% {
    transform: rotate(360deg);
  }
}

loading 类是加载中提示,默认透明度(opacity)为0,即该元素及其子元素默认不可见,通过 .htmx-request 类把透明度(opacity)改为1,变成可见状态,htmx-request 类被移除后容器又会变成不可见状态,即元素透明度(opacity)为0。

加载中的提示,加了一个 spin 旋转的动画,大家可以根据需要自定义任意加载中的动画,或者使用 GIF 等动画文件。

<body>
  <button hx-get="/load" hx-indicator=".loading">加载</button>
  <div class="loading"></div>
</body>

使用也很简单,在按钮中使用 hx-indicator 指定加载中动画的元素,这里使用了类名 .loading 的选择器(selector),点击按钮后,可以看到 loading 的类所在的元素多了一个类名 htmx-request ,变成了 class="loading htmx-request",这个就有了两个 CSS 类叠加作用于这个元素中。hx-get="/load" 有了响应后 htmx-request 类被移除,对应元素恢复到了默认状态。这样就实现了加载中的提示展示及隐藏。

htmx-request类

如果需要使用 GIF 等图片来展示加载中的动画提示,可以把上面的 loading 的 DIV 替换成 IMG 标签,或者把 IMG 标签放到 loading 的 DIV 标签内。

通过 htmx 使用加载中提示的重点是一定要在 CSS 中重写 htmx-request 类,控制可见不可见的方法有多种,除了以上示例中的透明度(opacity)外,还可以通过 display:none 及 display:block 来控制。只需要可见与不可见对应即可。

htmx 官方文档有提及到:如果没有明确的指示,则该类 htmx-request 将被添加到触发请求的元素中。也就是说,在我们以上的示例中,如果把按钮中的 hx-indicator=".loading" 内容去掉,这时候点击按钮,按钮就会被添加上 htmx-request 类。

htmx-request类

这样就可以根据实际情况灵活运用,比如有些操作只想在用户点击的按钮或菜单上显示加载中的状态动画,有些操作想要锁定锁定整个页面直至返回响应等。

运行这个示例的时候,可以看到 htmx 默认给页面添加了几个类:

hx-indicator

.htmx-indicator {
  opacity: 0
}

.htmx-request .htmx-indicator {
  opacity: 1;
  transition: opacity 200ms ease-in;
}

.htmx-request.htmx-indicator {
  opacity: 1;
  transition: opacity 200ms ease-in;
}

也就是说,如果是使用 GIF 之类的动画图片来表示加载中的状态的话,可以直接把元素的类设为 htmx-indicator ,htmx 就会自动接管加载中动画的显示与隐藏,无须自己再另行编写 CSS 代码。