HTMX扩展和以 ASP=.NET 核心使用HTMX
一. 导言导言 导言 导言 导言
HTMX 是一个强大的 JavaScript 库, 它使您能够以最小的 JawaScript @ . 创建动态网络应用程序。 它能让 AAX 请求 MS K1 交换 HTML 内容\ MPK2 并直接处理您的 HTMl 属性中的事件@. I' 在目前使用HTMX大约两年的时间里, 每个项目我都越来越了解它的能力\ I;,更重要的是, It_'s限制=.
不过我还是不知道 'T 声称对它有专业知识 我只是想分享一些 在路上学到的东西
附录 条款 本篇文章的焦点是 HTMX'}活动系统=,}扩展_,}和高级自定义@.}*ASP*NET核心融合模式(部分浏览)<,}HTMX.}NET}MS K7}♪和射程〞,}请见我的配套文章 □:} HTMX 与 ASP.NET 核心部分@:服务器 @-Side复兴.
事件活动
请求准备
请求准备阶段是 HTMX 在发送到服务器@ .} 这包括设置信头 @ MS K1} 添加参数 ,} 并处理用户输入.\ 。 在此阶段启动以下事件=:}
flowchart LR
A[htmx:configRequest] --> B[htmx:confirm] --> C[htmx:prompt] --> D[htmx:abort]
请求寿命周期
请求的生命周期阶段是 HTMX 向服务器发送请求并处理响应@.}在此阶段触发以下事件:
flowchart LR E[htmx:beforeRequest] --> F[htmx:request] --> G[htmx:afterRequest]
反应处理
反应处理阶段是HTMX处理服务器响应并更新 DOM.}在此阶段触发以下事件
flowchart LR
H[htmx:beforeOnLoad] --> I[htmx:onLoad]
I --> J[htmx:beforeSwap] --> K[htmx:swap] --> L[htmx:afterSwap]
L --> M[htmx:afterSettle] --> N[htmx:afterOnLoad]
历史管理
历史管理阶段是 HTMX 更新浏览器历史和 URL .}(以下事件在此阶段触发) @:
flowchart LR A[htmx:historyRestoreRequest] A --> B[htmx:historyPopped] B --> C[htmx:historyRestorePage]
您可以看到 HTMX 提供了一些事件, 您可以用来修改请求或响应@ , @ or even record *;}HTMX 因为是一个如此紧凑的系统而做一个LOT =\ MS K2 使用每一个这些您可以修改 HTM X 如何以非常全面的方式与服务器 {/} 客户端进行互动\ MPK4}
延长
HTMX最强大的一个方面是: 创建扩展名 来扩展它的能力... .... 在我看来... htmx:configRequest 以在请求中添加附加参数@.}当您想要将额外数据传送到服务器而不必修改 HTML 或 JavaScript 代码 . 时,此功能是有用的 @ action
其他分机可能会被勾钩 htmx:beforeRequest 在发送前修改请求@;}但 之后 勾勾勾 configRequest; 如 beforeRequest 类似的东西 HX-Vals 和 HX-Include在有效载荷中 [{\查询}).}已连接到 reuest {(} 。
你连勾钩都行 htmx:afterSwap 在内容被互换后执行动作@. @% 和客户端游戏库合并 阿尔卑斯山 或 文学 您可以以最小的代码创建强大的动态应用程序@ . @
HTMX 提供一些内建的“-”扩展名, 如 hx-boost 和 hx-swap-oob 允许您增强 HTMX 的功能, 不写入任何自定义代码@.}然而 @ , 有时需要创建您的扩展名以满足特定要求.
例如,您可能想要在您的请求中添加自定义信头@ ,}修改请求有效载荷 @ MS K2 或者以一种独特的方式处理特定事件\ .}
实现HTMX为您提供一些方便的整合点 @:
{
/**
* init(api)
* Called once when the extension is initialized.
* Use it to set up internal state, store references, or access HTMX utility functions via the api parameter.
*/
init: function(api) {
return null;
},
/**
* getSelectors()
* Returns additional CSS selectors that HTMX should monitor.
* Useful if your extension needs to handle custom elements or dynamic behavior.
*/
getSelectors: function() {
return null;
},
/**
* onEvent(name, evt)
* Called on every HTMX event (e.g., htmx:beforeRequest, htmx:afterSwap).
* Return false to cancel the event or stop propagation.
*/
onEvent: function(name, evt) {
return true;
},
/**
* transformResponse(text, xhr, elt)
* Modify the raw response text before it is parsed and swapped into the DOM.
* Use this to sanitize or preprocess HTML.
*/
transformResponse: function(text, xhr, elt) {
return text;
},
/**
* isInlineSwap(swapStyle)
* Return true if your extension will handle this swap style manually.
* This tells HTMX to skip default behavior.
*/
isInlineSwap: function(swapStyle) {
return false;
},
/**
* handleSwap(swapStyle, target, fragment, settleInfo)
* Perform custom DOM manipulation if you implement a custom swap style.
* Return true to prevent HTMX's default swap.
*/
handleSwap: function(swapStyle, target, fragment, settleInfo) {
return false;
},
/**
* encodeParameters(xhr, parameters, elt)
* Modify or serialize request parameters before sending.
* Return null to use default URL/form encoding.
* Return a string to override with a custom payload (e.g., JSON).
*/
encodeParameters: function(xhr, parameters, elt) {
return null;
}
}
HTMX 提供一些预设的“% -” 扩展件 有关在这里读取.
例如便用 内建的-in 扩展 json-encode 允许您在请求的正文中发送 JSON 数据, 而不是 URL -\encodd form drops data.。 如果您想要向服务器发送复杂的数据结构或数组, 这将有用@.}
您可以看到这个连接到 @ 3}事件中的钩子Name
init- 以设置扩展名并存储 HTMX API 的参考文件onEvent- 设置Content-Type标题到application/json当请求被配置时encodeParameters- 以推翻默认的 URL MS K1encoded 窗体编码, 并将参数序列化为 JSON}. 并返回一个字符串以防止 HTMX 使用默认 URl -enccod 表格编码@.
(function() {
let api
htmx.defineExtension('json-enc', {
init: function(apiRef) {
api = apiRef
},
onEvent: function(name, evt) {
if (name === 'htmx:configRequest') {
evt.detail.headers['Content-Type'] = 'application/json'
}
},
encodeParameters: function(xhr, parameters, elt) {
xhr.overrideMimeType('text/json')
const object = {}
parameters.forEach(function(value, key) {
if (Object.hasOwn(object, key)) {
if (!Array.isArray(object[key])) {
object[key] = [object[key]]
}
object[key].push(value)
} else {
object[key] = value
}
})
const vals = api.getExpressionVars(elt)
Object.keys(object).forEach(function(key) {
// FormData encodes values as strings, restore hx-vals/hx-vars with their initial types
object[key] = Object.hasOwn(vals, key) ? vals[key] : object[key]
})
return (JSON.stringify(object))
}
})
})()
甚至更简单但甚至更简单的人类 hx-debug 附加外加 HX-Debug 请求标题@.}% 此选项可用于调试和记录目的 @ , 因为它允许您在 dev control@ MS K2 中查看原始请求和响应数据 。
(function() {
htmx.defineExtension('debug', {
onEvent: function(name, evt) {
if (console.debug) {
console.debug(name, evt)
} else if (console) {
console.log('DEBUG:', name, evt)
} else {
throw new Error('NO CONSOLE SUPPORTED')
}
}
})
})()
{\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}包括一个强大的 客户端侧推演扩展名 它允许您使用客户端@ - @ spide tableing 库将返回的 JSON 数据转换为 HTML\ @ MS K1} 这将有利于创建动态 UI, 而不必依赖服务器@ MPK2side Mading+.}
一些自定义扩展名
动态行编号
例如,在最近的一个项目中,我使用HTMX OOB 互换来更新表格中的数行“.” 为了做到这一点,我想知道表格中目前显示的行是几行 @,}所以我只更新了可见的行@.。
延长
export default {
encodeParameters: function (xhr, parameters, elt) {
const ext = elt.getAttribute('hx-ext') || '';
if (!ext.split(',').map(e => e.trim()).includes('dynamic-rowids')) {
return null; // Use default behavior
}
const id = elt.dataset.id;
const approve = elt.dataset.approve === 'true';
const minimal = elt.dataset.minimal === 'true';
const single = elt.dataset.single === 'true';
const target = elt.dataset.target;
const payload = { id, approve, minimal, single };
if (approve && target) {
const table = document.querySelector(target);
if (table) {
const rowIds = Array.from(table.querySelectorAll('tr[id^="row-"]'))
.map(row => row.id.replace('row-', ''));
payload.rowIds = rowIds;
}
}
// Merge payload into the parameters object
Object.assign(parameters, payload);
return null; // Return null to continue with default URL-encoded form encoding
}
}
使用它
要使用它,我们需要在我们的 HTMX 配置中添加扩展名@. @% 所以在您的入境点 js 文件 @ ( @ avoid you@ MS K1_ re 使用模块 @ I; @ yoy 应该是\ )} 您可以做类似的事情吗?
import dynamicRowIds from "./dynamicRowIds"; // Load the file
htmx.defineExtension("dynamic-rowids", dynamicRowIds); // Register the extension
然后在任意元素上您想要使用它, 您可以添加 hx-ext 值的属性 dynamic-rowids.
<button
hx-ext="dynamic-rowids"
data-target="#my-table"
data-id="@Model.Id"
data-param1="true"
data-param2="false"
data-param3="@Model.Whatever"
hx-post
hx-controller="Contoller"
hx-action="Action"
>
<i class='bx bx-check text-xl text-white'></i>
</button>
保留参数
这是另一个简单的 HTMX 扩展@ , @% 此时间连接到 htmx:configRequest 在请求发送前, 正在修改 URL @ '@ 此扩展名很方便, 如果您使用基于查询的过滤器等@ MS K2 @ 并且您想要一些请求来保存现有的过滤器, 而其它请求则不是 @ MPK4 @ @ e @ MOSK5} @ g,} @ MIsk@ name_ '}和 @ I'_ startdate 但不是 @ OMK11page+'} 或 @ MCK13sort}').}
这是SMIILAR, 与现有的 HTMX 扩展号不完全相同 plip - 参数
延长
你可以看到我们勾钩 onEvent 收听 htmx:configRequest 事件@. @
然后我们 :
- 获取触发事件元素
- 获取
preserve-params-exclude从元素属性 {(} {如果它存在)}\ \ 并且将其分割成一系列密钥以排除\ ( 因此我们用\ MPK3t 在请求中添加它们@) - 从窗口位置获取当前 URL 参数
- 从请求 URL获取新参数
- 环绕当前参数并检查它们是否在排除列表中,是否已经进入新参数
- 如果它们不是,,我们就把它们加入新参数
- 最后,我们为请求的 URL 设置了新参数并返回真实状态以继续此请求@.}
export default {
onEvent: function (name, evt) {
if (name !== 'htmx:configRequest') return;
const el = evt.detail.elt;
const excludeStr = el.getAttribute('preserve-params-exclude') || '';
const exclude = excludeStr.split(',').map(s => s.trim());
const currentParams = new URLSearchParams(window.location.search);
const newParams = new URLSearchParams(evt.detail.path.split('?')[1] || '');
currentParams.forEach((value, key) => {
if (!exclude.includes(key) && !newParams.has(key)) {
newParams.set(key, value);
}
});
evt.detail.path = evt.detail.path.split('?')[0] + '?' + newParams.toString();
return true;
}
};
在这里,我用的是关键 HTMX.Net 标签中的标记帮助@. @ the likes hx-controller 和 hx-action 用于为您生成正确的 HTMX 属性的标签助手@ .以及 hx-route-<x> 用于在路由中传递的值@.}这非常有用,因为它允许您使用 C#}代码为属性生成正确的值,而不必在 HTML}.}}
使用它
作为扩展名@ ' @%s 非常简单, 可以使用 :} @
首先,我们需要在我们的 HTMX 配置中添加扩展@. @%
import preserveParams from './preserveParams.js';
htmx.defineExtension('preserve-params', preserveParams);
autload'您會注意到 預設的 HTMX 延伸使用 {'} 自行載入延伸@ .} 的方法 。
// Autoloading the extension and registering it
(function() {
htmx.defineExtension('debug', {
}
如果您在非“-”的环境下使用 HTMX 来应用HTMX, 这是一个很好的方法。 但是如果您在 “'” 中使用了“MS K5” 模块,你应该使用该模块 import 用于加载扩展名的语句,然后明确将其注册为对您的 htmx 例. 这只允许您利用树枝 -shaking, 只装入您需要的扩展名@.
然后在元素上,您可以添加 hx-ext 值的属性 preserve-params 和 preserve-params-exclude 属性,带有逗号分隔的参数列表,从请求中排除@.
<a class="btn-outline-icon"
hx-controller="MyController"
hx-action="MyAction"
hx-route-myparam="@MyParam"
hx-push-url="true"
hx-ext="preserve-params"
preserve-params-exclude="page,sort"
hx-target="#page-content"
hx-swap="innerHTML show:top"
hx-indicator>
<i class="bx bx-search"></i>
</a>
在本案中,由于 event.detail.path 新的 myparam 以我们的新值替换此值, 但保存所有其他的@(}除此以外 page 和 sort@ )._ @ 这样我们就可以一直把在 URL 中设置的任何过滤器传送到服务器上, 而不必担心当我们提出新请求时这些过滤器会丢失@.} @
ASP=.NET核心
HTMX 的精美之处之一是,它与服务器的许多互动是通过 HTTP headers @.}这些信头为服务器提供了丰富的背景信息。 这些信头让您能够从 [email protected]核心端点或 Razor 视图中做出适当回应。
同样,这方面的一个关键组成部分是: HTMX.Net它提供的许多物品都很整洁。 Request 用于确定 HTMX 是否提出了HTMX请求,或未提出@,}并相应处理该请求。 @.
它还有自己的机制来发送触发器
Response.Htmx(h => {
h.WithTrigger("yes")
.WithTrigger("cool", timing: HtmxTriggerTiming.AfterSettle)
.WithTrigger("neat", new { valueForFrontEnd= 42, status= "Done!" }, timing: HtmxTriggerTiming.AfterSwap);
});
Push Urls etquals equist situ %s ... etc=... _# Khalid做了一个伟大的工作,创建了一套扩展功能,使HTMX在ASP*.NET Core.}中易于与 HTMX合作。
在使用 HTMX 和 ASP+.NET Core. 时, 它是工具箱中的一个关键工具 检查一下吧,!
HTMX 通用HTMX请求信头
这里“ ’” 列出最有用的信头 HTMX发送的明细表, 每一份请求都加上“ I: ”
| #标题 @ | }描述: # | # | |
|---|---|---|---|
| HX- 请求@ | 对 HTMX- 启动的请求总是设定为真实的 @.Great 用于检测中器或控制器中的HTMX呼叫@MS K5# | } | |
| +HX-+Target+ | +DOM目标元素的代号,即该响应将被转换成 @.+Q | +# | |
| 触发此请求的元素的代号 @( @[email protected]}.}一个纽扣 @MS K6_Q# | { | ||
| “ | ”HX-Trigger-Name | 触发元素的名称 @(}用于窗体的“). | # |
| +HX-+Prompt@ | }包含来自 hx @-_proppt+.+# | 的用户输入 | |
| 请求启动时的浏览器 URL @.}对记录和上下文有用的@. @ | # | ||
| 如果请求是导航后历史恢复的一部分, 请按实情发送@ | @e_(# ..,背按钮 @).} @MS K9} |
请求延期
我在ASP=.NET Core Apps.}结合HTMX}.Net这样的网络中广泛使用这些 Request.IsHtmx() , Request.IsHtmxBoosted() 和 Request.IsHtmxNonBoosted() 您可以很容易地检测到 HTMX 请求并相应响应@. @%
例如“,我有一个非常简单的扩展名请求, 让我可以检测一下是否某项请求针对我的主机 #page-content 如果是这样的话,我知道我应该寄回一个部分 .
Onte: @ 许多 donoks'} 意識到您可以指定一个 page@ '_ full page '}為部份@ MPK4} 它會跳過佈局.}
if (Request.PageContentTarget())
{
Response.PushUrl(Request);
return PartialView("List", vm);
}
return View("List", vm);
public static class RequestExtensions
{
public static bool PageContentTarget(this HttpRequest request)
{
bool isPageContentTarget = request.Headers.TryGetValue("hx-target", out var pageContentHeader)
&& pageContentHeader == "page-content";
return isPageContentTarget;
}
}
回应延长
除了请求扩展@ ,, 您还可以创建响应延伸来将事件发回客户端@ MPK1。 这对启动客户端侧边活动有帮助 @ MS K2
甜快示例
例如 在我的SweetAlert 2整合中 我启用了从服务器设定的触发器来关闭对话框@ .
document.body.addEventListener('sweetalert:close', closeSweetAlertLoader);
这是由服务器作为 HTMX 触发事件启动的@. @%
public static void CloseSweetAlert(this HttpResponse response)
{
response.Headers.Append("HX-Trigger" , JsonSerializer.Serialize(new
{
sweetalert = "close"
}));
}
这将触发 sweetalert:close 允许您关闭对话框@.} 您也可以使用此功能将数据传送给客户端 HX-Trigger header. 用于将数据从服务器传送到客户端,而不必修改 HTML 或 JavaScript 代码@.
正如你所看到的那样,通过在身体上添加一个活动听众来听这些节目很容易死。 我主要使用JSON, 因为它总是正确编码:.。
显示 toast
以前我写过吐司方法 在这里@,}(但这里值得一提) 和@.}非常简单地让服务器触发客户方的敬酒通知
public static void ShowToast(this HttpResponse response, string message, bool success = true)
{
response.Headers.Append("HX-Trigger", JsonSerializer.Serialize(new
{
showToast = new
{
toast = message,
issuccess =success
}
}));
}
然后我就勾入事件客户的侧面 打电话给我 showToast 函数@. @%
import { showToast, showHTMXToast } from './toast';
window.showHTMXToast = showHTMXToast;
document.body.addEventListener("showToast", showHTMXToast);
这又呼唤我, showToast 和 well@,}显示一个烤面包_;}再次看到更多关于它的内容 条款内 .
export function showHTMXToast(event) {
const xhr = event?.detail?.xhr;
let type = 'success';
let message = xhr?.responseText || 'Done!';
try {
const data = xhr ? JSON.parse(xhr.responseText) : event.detail;
if (data.toast) message = data.toast;
if ('issuccess' in data) {
type = data.issuccess === false ? 'error' : 'success';
} else if (xhr?.status >= 400) {
type = 'error';
} else if (xhr?.status >= 300) {
type = 'warning';
}
} catch {
if (xhr?.status >= 400) type = 'error';
else if (xhr?.status >= 300) type = 'warning';
}
showToast(message, 3000, type);
}
在结论中的结论
希望您觉得这段话有用且内容丰富, 若有任何问题或评论请在「.」以下留言:
本博客上的相关文章
随带条款
此篇文章是 HTMX 与 ASP @.}NET Core: 的两集中的一部分。
- 带有 ASP.NET 核心部件的 HTMX @- 聚焦于 ASP.NET核心整合@,部分观点 @MS K3}HTMX.NetMSKO5和页码
- 本条本条 - 深潜到 HTMX 事件@, 寿命周期 @, 扩展架构_, 和自定义延伸
更多HTMX文章
- 添加 HTMX 的呼叫 使用 HTMX 执行射速
- ASP.NET 核心缓存与 HTMX 满足HTMX要求的缓冲战略
- 使用阿尔卑斯山和HTMX的自动-refresh - 将阿尔卑斯山与HTMX结合用于反应组件
- 使用 HTMX 使您的站点更像 SPA @ - - SPA- 类似没有 JavaScript 框架的导航
- HX 指标使用 SweetAlert 使用 HTMX 的漂亮装货指标
- 使用 HTMX 显示通吐和互换 @ -_ 服务器@ MS K1_ 触发吐司通知
继续阅读
HTMX 官方文档@: @%
- HTMX文件文档 官方HTMX文件
- HTMX 事件参考 - HTMX事件完整列表
- HTMX 扩展 -官方 HTMX 扩展
- HTMX 示例 HTMX模式的实例
- HTMX 论文 有关HTMX哲学的深思熟虑的文章
圖書館&工具MS K1
- HTMX.NET 吉特Hub -HTMX.NET图书馆源代码
- HTMX.NET NUGet @-_HTMX.NET 在 Nuget 上
- Khalid Abuhakmeh_'网站 HTMX .NET的创建者
- AlpineMSMK0js 文档 -官方阿尔卑斯山 MS K1js docs
社区资源@: