通常网页要向后台提交数据都通过表单的方式进行,但有时候为了兼顾网页的布局美观,很难把所有的用户输入控件都放在同一个 <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不会提交该元素的值。