HTMX实现无表单提交的妙招:解锁更简洁高效的交互方式

2025-01-08阅读数:80
上一篇:HTMX 不生效?探索 JavaScript 动态 HTML 加载的终极解决方案
下一篇:C03 - Python爬虫练习通关提示

通常网页要向后台提交数据都通过表单的方式进行,但有时候为了兼顾网页的布局美观,很难把所有的用户输入控件都放在同一个 <form> 表单标签里面。以往要解决这样的问题只能通过编写JavaScript代码来实现。

htmx拥有强大的交互能力,能够在跨表单甚至无表单的情况下对数据进行提交,而且只需要设置一个属性值即可实现,无须编写大量JavaScript代码。

下面我们就使用 Python + flask + htmx 来演示一下htmx的无表单提交功能。

先建一个演示的项目,使用Python + flask + htmx作为示例,项目总共两个子文件夹:templates、static;3个文件:main.py,templates/index.html,static/htmx2.0.3.min.js,项目目录结构按flask的默认结构。

main.py

from flask import Flask, render_template,request

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')


@app.route('/commit', methods=['POST'])
def login():
    return f"Hello {request.form['name']}"


if __name__ == '__main__':
    app.run(debug=True)

index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="static/htmx2.0.3.min.js"></script>
    <title>gethtmx.com</title>
    <style>
        #myform {
            margin: 100px auto auto auto;
            width: 640px;
            padding: 20px;
            border: 1px solid #ccc;
            border-radius: 5px;
        }
        input{
            height: 40px;
            width: 100%;
            margin-bottom: 30px;
            box-sizing: border-box;
        }
        button{
            height: 40px;
            width: 100%;
            background-color: #1c1c1c;
            color: white;
            border: none;
            border-radius: 5px;
        }
        button:hover{
            background-color: #333;
        }
        #result {
            margin: auto;
        }
    </style>
</head>

<body>
    <div id="myform">
        <label for="name">Name:</label>
        <input type="text" name="name" id="name" required>
        <br>
        <label for="email">Email:</label>
        <input type="email" name="email" id="email" required>
        <br>
        <button type="submit" hx-post="commit" hx-target="#result" hx-include="#name,#email">Submit</button>
        <div id="result"></div>
    </div>
</body>

</html>

在 index.html 中,myform中有两个表单控件,分别是name、email,通过按钮触发事件,在按钮的属性中加入 hx-post 。可以看到,整个页面都没有用到常规的 <form> 标签,但运行项目,输入内容,点击按钮就能看到表单已经提交成功并接收到了后台的反馈。这个提交的功能实现主要得益于 hx-include 属性。

hx-include 有多种取值方法:

  • 要包含的元素的 CSS 查询选择器。
  • this它将包括元素的后代。
  • closest 它将找到 与给定的 CSS 选择器匹配的最近的closest tr祖先元素或其自身(例如,将定位到离元素最近的表行)。
  • find 它将找到与给定的 CSS 选择器匹配的第一个子后代元素。
  • next 它将向前扫描 DOM 以查找与给定 CSS 选择器匹配的第一个元素。(例如,next .error将定位到具有类的最近的以下同级元素error)
  • previous 它将向后扫描 DOM 以查找与给定 CSS 选择器匹配的第一个元素。(例如,previous .error将定位到具有类的最近的前一个兄弟元素error)

根据 htmx 的官网说明,hx-include只需要通过网页元素ID就可以获取它的值并向后台进行提交,并且可以同时指定多个元素,每个元素的ID用英文逗号分隔。

以上的示例其实还不能完全体现出 htmx 在表单提交上的优势,如果是换成常见的数据查询页面就能更好地应用。

例如:页面顶部有一个搜索框,中间是数据,底部是分页,需要同时向后台提交搜索框中的关键字及分页的页码,因为这两者的布局隔得太远,没办法放在同一个 <form> ,使用VUE、React或者Bootstrap等框架时,通常是结合JavaScript代码交给组件处理。

但使用htmx的话,只需要在负责触发提交动作的元素上加上hx-include属性即可。

需要注意的是:hx-include默认是以form data的形式向后台进行提交的,所以包含的元素中必须有name属性,否则hx-include不会提交该元素的值。