NOTE: Apart from
(and even then it's questionable, I'm Scottish). These are machine translated in languages I don't read. If they're terrible please contact me.
You can see how this translation was done in this article.
Friday, 02 May 2025
//11 minute read
HTMX on tehokas JavaScript-kirjasto, jonka avulla voit luoda dynaamisia verkkosovelluksia minimaalisella JavaScriptilla. Sen avulla voit tehdä AJAX-pyyntöjä, vaihtaa HTML-sisältöä ja käsitellä tapahtumia suoraan HTML-ominaisuuksissasi. Olen käyttänyt HTMX:ää noin kaksi vuotta tässä vaiheessa, ja jokaisen projektin myötä opin yhä enemmän sen kyvyistä, ja mikä tärkeintä, kyse on rajoituksista.
En kuitenkaan edelleenkään väitä, että minulla olisi asiantuntevaa tietoa siitä. Halusin vain kertoa asioista, joita olen oppinut matkan varrella.
Kuten näet, HTMX tarjoaa useita tapahtumia, joihin voit kytkeytyä muuttaaksesi pyyntöä tai vastausta. Käyttämällä jokaista näistä voit muokata HTMX:n vuorovaikutusta palvelimen / asiakkaan kanssa melko kattavasti.
Yksi HTMX:n tehokkaimmista puolista on kyky luo laajennuksia laajentaakseen valmiuksiaan. Omassa tapauksessani yleensä koukkaan htmx:configRequest
lisäparametrien lisääminen pyyntöön. Tämä on hyödyllistä, kun haluat siirtää lisätietoja palvelimelle tarvitsematta muuttaa HTML- tai JavaScript-koodia.
Muut laajennukset saattavat koukuttaa htmx:beforeRequest
muuttaa pyyntöä ennen sen lähettämistä, mutta jälkeen eniten muita laajennuksia, jotka koukuttavat configRequest
; kuten beforeRequest
jutut kuten HX-Vals
sekä HX-Include
S on jo kiinni reuestissa (joko hyötykuormassa \ kyselystringissä).
Voit jopa koukuttaa htmx:afterSwap
Suorittaa toimintoja sen jälkeen, kun sisältö on vaihdettu. Yhdistettynä asiakaspuolen tempauskirjastoihin kuten Alppi.js tai Lit voit luoda voimakkaita dynaamisia sovelluksia, joissa on minimaalinen koodi.
HTMX tarjoaa joitakin sisäänrakennettuja laajennuksia, kuten hx-boost
sekä hx-swap-oob
joiden avulla voit parantaa HTMX:n toiminnallisuutta kirjoittamatta mitään mukautettua koodia. Joskus on kuitenkin tehtävä omat laajennukset vastaamaan tiettyjä vaatimuksia.
Voit esimerkiksi haluta lisätä omia otsikoita pyyntöihisi, muuttaa pyynnön hyötykuormaa tai käsitellä tiettyjä tapahtumia ainutlaatuisella tavalla.
Tämän HTMX:n avulla saat kätevät integraatiopisteet:
{
/**
* 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 tarjoaa useita valmiiksi rakennettuja laajennuksia, joita voit Lue aiheesta täältä.
Esimerkiksi kätevä sisäänrakennettu laajennus json-encode
Voit lähettää JSON-tietoja pyyntöelimessä URL-koodattujen tietojen sijaan. Tämä on hyödyllistä, kun haluat lähettää monimutkaisia datarakenteita tai -sarjoja palvelimelle.
Huomaat, että tämä liittyy kolmeen tapahtumaan
init
- laajennuksen perustamiseen ja HTMX-rajapintaa koskevan viittauksen tallentamiseenonEvent
- asettaa Content-Type
Otsikko application/json
kun pyyntöä konfiguroidaanencodeParameters
- ohittaaksesi URL-koodatun oletusmuodon koodaamalla ja sarjaamalla muuttujat JSONiksi. Se palauttaa myös merkkijonon, joka estää HTMX:ää käyttämästä URL-koodattua oletusmuotoa.(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))
}
})
})()
Tai jopa yksinkertaisempi, mutta vielä enemmän käsialaa hx-debug
Laajennus, jolla lisätään HX-Debug
Kohti pyyntöä. Tämä on hyödyllistä vianetsintä- ja kirjaustarkoituksiin, koska sen avulla voit nähdä raa'an pyynnön ja vastaustiedot dev-konsolissa.
(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')
}
}
})
})()
Niitä on paljon enemmän, mukaan lukien erittäin voimakas asiakaspuoli tempaisee laajennusta jonka avulla voit käyttää asiakaspuolen tempauskirjastoja muuttaaksesi palautetun JSON-datan HTML:ksi. Tästä on hyötyä dynaamisen käyttöliittymän luomisessa tarvitsematta luottaa palvelimen renderointiin.
Esimerkiksi tuoreessa projektissa käytin HTMX OMB -swapeja taulukon useiden rivien päivittämiseen. Tätä varten halusin tietää, mitkä rivit ovat tällä hetkellä esillä pöydässä, joten päivitin vain näkyvät rivit.
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
}
}
Käyttääksemme sitä meidän täytyy lisätä laajennus HTMX-kokoonpanoomme. Joten syöttökohdassa js-tiedostossa (olettaen, että käytät moduuleja; sinun pitäisi olla) voit tehdä jotain tällaista:
import dynamicRowIds from "./dynamicRowIds"; // Load the file
htmx.defineExtension("dynamic-rowids", dynamicRowIds); // Register the extension
Sitten mihin tahansa elementtiin haluat käyttää sitä voit lisätä hx-ext
Ominaisuus arvolla 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>
Tämä on toinen yksinkertainen HTMX-laajennus, tällä kertaa kytkettynä htmx:configRequest
Kun muokkaamme URL-osoitetta ennen pyynnön lähettämistä. Tämä laajennus on kätevä, jos käytät querystring-pohjaista suodatusta jne. Ja haluat joidenkin pyyntöjen säilyttävän olemassa olevat suodattimet, kun taas toiset eivät (esim. "nimi" ja "aloituspäivä", mutta eivät "sivu" tai "sort".
Tämä on SIMILAR, mutta ei aivan sama kuin nykyinen HTMX-laajennus push-paramit
Huomaat, että me koukkaamme onEvent
Kuunnellaan htmx:configRequest
tapahtuma.
Sitten me:
preserve-params-exclude
Määritä elementti (jos se on olemassa) ja jaa se erinäisiin avaimiin suljettavaksi (joten emme lisää niitä pyyntöön)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;
}
};
Tässä käytän olennaista HTMX.Net sen lapuille auttajille. Kaltaiset hx-controller
sekä hx-action
ovat tunnisteiden auttajia, jotka luovat sinulle oikeat HTMX-ominaisuudet. Kuten myös hx-route-<x>
jotta arvot kulkevat reitillä. Tämä on todella hyödyllistä, koska sen avulla voit käyttää C#-koodia luodaksesi oikeat arvot attribuuteille sen sijaan, että joutuisit koodaamaan ne HTML:ssäsi.
Laajennuksena sitä on todella helppo käyttää:
Ensin meidän on lisättävä laajennus HTMX-kokoonpanoomme.
import preserveParams from './preserveParams.js';
htmx.defineExtension('preserve-params', preserveParams);
HUOMAUTUS: Huomaat, että HTMX-laajennukset lataavat laajennuksen automaattisesti.
// Autoloading the extension and registering it
(function() {
htmx.defineExtension('debug', {
}
Tämä on hyvä tapa tehdä se, jos käytät HTMX:ää muussa kuin moduuliympäristössä. Jos kuitenkin käytät moduuleja (mikä sinun pitäisi olla) on parempi käyttää import
Ilmoitus laajennuksen lataamisesta ja sen jälkeen nimenomaisesti rekisteröi se omaasi vastaan htmx
inspiraatiota. Näin voit hyödyntää puiden ravistelua ja ladata vain tarvitsemasi laajennukset.
Sitten oman elementin voit lisätä hx-ext
Ominaisuus arvolla preserve-params
ja preserve-params-exclude
Attribuutti, jossa on pilkkueroteltu luettelo muuttujista, jotka voidaan jättää pyynnön ulkopuolelle.
<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>
Tässä tapauksessa syynä on event.detail.path
uuden saaminen myparam
Arvolla se korvaa sen uudella arvollamme, mutta säilyttää kaikki muut (paitsi page
sekä sort
). Voimme siis edelleen siirtää URL-osoitteeseen asettamamme suodattimet palvelimelle ilman, että meidän tarvitsee olla huolissamme niiden katoamisesta, kun teemme uuden pyynnön.
Yksi HTMX:n hienoimmista puolista on se, että sen vuorovaikutus palvelimen kanssa tapahtuu HTTP-otsikoiden kautta. Nämä otsikot tarjoavat palvelimelle runsaan kontekstin siitä, mikä laukaisi pyynnön, jolloin voit vastata sopivasti ASP.NET-päätepisteistäsi tai Razor-näkymistäsi.
Jälleen yksi keskeinen tekijä tässä on HTMX.Net...................................................................................................................................... Monet sen tarjoamat tuotteet ovat näppäriä Request
laajennukset HTMX-pyyntöjen havaitsemiseksi. Tämä on hyödyllistä sen määrittämiseksi, onko pyynnön tehnyt HTMX vai ei, ja sen mukaan.
Sillä on myös oma mekanisminsa laukaisimien lähettämiseksi
Response.Htmx(h => {
h.WithTrigger("yes")
.WithTrigger("cool", timing: HtmxTriggerTiming.AfterSettle)
.WithTrigger("neat", new { valueForFrontEnd= 42, status= "Done!" }, timing: HtmxTriggerTiming.AfterSwap);
});
Työnnä Urls ym.... jne. Khalid teki loistavaa työtä luodessaan laajennuksia, joiden avulla HTMX:n kanssa on helppo työskennellä ASP.NET Coressa.
Se on avaintyökalu työkalupakissani, kun työskentelen HTMX:n ja ASP.NET Coren kanssa. Katso tätä!
Tässä HTMX:n kannattavimpien otsikoiden erittely jokaisen pyynnön yhteydessä:
Otsikko Kuvaus Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko Otsikko |----------------------------|------------------------------------------------------------------------------------------------------------------| HX-Pyynnöt aina HTMX-pyyntöön. Hyvä havaitsemaan HTMX-puheluita keskiohjelmistoissa tai ohjaimissa. ......................................................................... HX-Target DOM:n kohdeelementin tunniste, johon vastaus vaihdetaan. ......................................................................... HX-Trigger Pyynnön aiheuttaneen tekijän henkilöllisyys (esim. nappi). ......................................................................... HX-Trigger-Nimi Laukaisimen nimi (täytteenä lomakkeet). ......................................................................... HX-Prompt sisältää käyttäjäsyötteitä HX-promptista. ......................................................................... HX-Current-URL-selaimen URL-osoite, kun pyyntö esitettiin. Hyödyllistä puunkorjuussa ja kontekstissa. ......................................................................... HX-History-Restory-Pyynnöksen lähettäminen on totta, jos pyyntö on osa navigoinnin jälkeistä historian restaurointia (esim. takapainike). .........................................................................
Käytän näitä aika laajasti ASP.NET Core -sovelluksissani. Yhdistettynä HTMX-verkkoihin, kuten Request.IsHtmx()
, Request.IsHtmxBoosted()
sekä Request.IsHtmxNonBoosted()
HTMX-pyynnöt voi helposti havaita ja niihin voi vastata sen mukaan.
Minulla on esimerkiksi todella yksinkertainen laajennus pyynnölle, jonka avulla voin havaita, jos pyyntö kohdistuu pääosaani #page-content
div. Jos on, niin tiedän, että minun pitäisi lähettää osittainen takaisin.
HUOMAUTUS: Monet eivät ymmärrä, että "täysi sivu" voidaan määritellä osittaiseksi, sitten se vain ohittaa layoutin.
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;
}
}
Pyydä-laajennusten lisäksi voit myös luoda Response-laajennuksia lähettääksesi tapahtumia takaisin asiakkaalle. Tästä on hyötyä asiakassivutapahtumien käynnistämisessä.
Esimerkiksi SweetAlert2-integraatiossani Sallin ikkunan sulkemisen palvelimen asettamalla liipaisimella.
document.body.addEventListener('sweetalert:close', closeSweetAlertLoader);
Tämä laukeaa palvelimelta HTMX-laukaisimena.
public static void CloseSweetAlert(this HttpResponse response)
{
response.Headers.Append("HX-Trigger" , JsonSerializer.Serialize(new
{
sweetalert = "close"
}));
}
Tämä laukaisee sweetalert:close
Tapahtuma asiakaspuolella, jolloin voit sulkea dialogin. Voit myös siirtää dataa takaisin asiakkaalle käyttämällä HX-Trigger
Otsikko. Tämä on hyödyllistä tietojen siirtämiseksi palvelimelta asiakkaalle ilman HTML- tai JavaScript-koodin muuttamista.
Kuten näet, näitä tapahtumia on helppo kuunnella vain lisäämällä tapahtuman kuuntelija kehoon. Käytän JSONia pääasiassa siten, että se koodaa aina oikein.
Kirjoitin paahtomenetelmästäni aiemmin täälläMutta se kannattaa mainita tässäkin. Jotta palvelin voisi yksinkertaisesti käynnistää paahtopuheilmoituksen asiakaspuolella. Asetin liipaisimen tähän Response-laajennukseen.
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
}
}));
}
Sitten liityn tapahtuman asiakaspuoleen ja soitan showToast
Funktio.
import { showToast, showHTMXToast } from './toast';
window.showHTMXToast = showHTMXToast;
document.body.addEventListener("showToast", showHTMXToast);
Tämä tulee sitten minun luokseni. showToast
Toimi ja hyvin, osoittaa paahtoleipää; katso siitä lisää artikkelissa .
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);
}
Siinä se, pyörremyrskykiertue HTMX:stä ja ASP.NET Coresta. Toivottavasti pidit sitä hyödyllisenä ja informatiivisena. Jos sinulla on kysyttävää tai kommentteja, kommentoi alla.