Якщо ви створили традиційні програми для роботи з ядром MVC ASP. NET, вам відомі проблеми: страшні " блимання " під час переходу між сторінками користувачів. Перезавантаження сторінок, хромування браузера, перестрибування вмісту у вигляді нової сторінки. Це працює, але це не працює feel Сучасно.
Техніка повернення часткових фрагментів HTML з сервера і заміни їх на DOM вирішує це - і це не є чимось новим. Я використовував цей шаблон з днів jquery, і навіть до того за допомогою ваніля JavaScript, XMLHttpRequest. Що змінилося, так це те, як елегантний Це стає з HTMX.
HTMX надає нам змогу зробити те, що ми завжди робили: повернути HTML- відпущений сервер і поміняти його на сторінку. Немає більше написання нетипового JavaScript для кожної взаємодії. Більше не буде вибору між " правильним " розвитком сервера і плавним досвідом користувача. З HTMX ми отримаємо обидва варіанти.
Стаття подружнього партнера: Ця стаття зосереджується на стороні інтеграції ядра ASP. NET. Для глибокого занурення у події HTMX, життєвий цикл і нетипові розширення дивіться мою супровідну статтю: A Wistle- stop Tour of HTMX Extensions and Використовується HTMX з ядром ASP. NET.
У цій статті я покажу вам, як HTMX чудово інтегрується з ядром ASP.NET, як чудові HTMX. NET бібліотека робить його ще кращим, і як мій threelucid.pproginghelper У пакунку NuGe використовується HTMX з мінімальним налаштуванням потужної пагінії.
Цей підхід також стосується оболонок - доданий шаблон Django у версії 6. 0, у Рейлів є блоки Turbo, а ширша веб- екосистема охоплює HTML- перезаряджні шаблони. Тепер слушний час для створення програм, що працюють на сервері.
HTMX - це бібліотека, яка надає вам доступ до сучасних можливостей навігатора безпосередньо з HTML, а не написання JavaScript. Вона розширює HTML атрибутами, які надають вам змогу створювати запити AJAX, обмінюватися та створювати багаті взаємодії - все це без залишення розмітки.
Атрибути ключів, які ви використовуватимете найчастіше:
hx-get, hx-post, hx-put, hx-delete - Робити запити HTTPhx-target - Вкажіть місце відповідіhx-swap - Керуйте тим, як буде змінено вміст (interHTML, зовнішній HTML тощо)hx-trigger - Визначте, що викликає запит (клацніть, змініть, завантажте тощо)hx-push-url - Оновлювати URL навігатора без перезавантаження повної сторінкиОсь її краса: ви все ще пишете код на сервері, повернений до роботи HTML. Немає API JSON, без шаблонів клієнтів, без трубопроводів для збирання. Просто старий HTML за допомогою дроту.
Перед HTMX ми досягли такого ж ефекту з набагато більшою церемонією.
// jQuery circa 2010
$('#load-more').click(function() {
$.ajax({
url: '/posts/page/' + currentPage,
success: function(html) {
$('#posts-container').append(html);
currentPage++;
}
});
});
І ще раніше, з ванільним JavaScript:
// Vanilla JS circa 2005
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
document.getElementById('content').innerHTML = xhr.responseText;
}
};
xhr.open('GET', '/partial-content', true);
xhr.send();
Шаблон з боку сервера був ідентичним - повернути фрагменти HTML, поміняти їх на DOM. HTMX просто пересуває цю логіку з JavaScript у HTML- атрибути, роблячи її декламованою, придатною для виявлення, і набагато меншою кількістю помилок. Інновації - це не техніка, а інтерфейс.
Розробники ASP. NET вже роками це роблять. IndatePanels у WebForms (2005), PartialView() в MVC с самого первого дня, Html.RenderAction() Те, чого нам бракувало, було елегантним, стандартизованим способом прослуховувати його на стороні клієнта.
Широка промисловість також відновила ці шаблони. Терміни на зразок " серверний показ ," " гібридне відображення ," " архітектура " і " belands " в основному описують те, які оболонки завжди робилися, але зі свіжими очима. Перевірка того, що масштаби, виконання дій сервера, виконання і - за допомогою правильних інструментів - є чудовим досвідом для користувачів.
Спочатку включіть до вашого компонування HTMX. Ви можете скористатися CDN або надати його локально:
<script src="https://unpkg.com/htmx.org@2.0.0"></script>
Ось і все. ніяких кроків збирання, ніякого встановлення npm, налаштування веб-пакунку.
Для реагування на клієнтську частину (показати/ ховати елементи, перемикати стан, локальний стан інтерфейсу користувача) Альпійський.js ідеально доповнює HTMX. Лише за допомогою 15KB gzip у програмі передбачено декартову реанімацію, схожу на Vue/ React- act, без loat.
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
Ось як вони працюють разом:
<div x-data="{ open: false }">
<button x-on:click="open = !open">Toggle</button>
<div x-show="open" x-transition>
<button hx-get="/api/data" hx-target="#results">Load Data</button>
</div>
</div>
Альпійська система керує локальним інтерфейсом користувача (перемиканням), HTMX керує викликами серверів (подача даних). У цій статті ви побачите цей зразок - альпійський для реагування клієнта, HTMX для взаємодії з сервером.
Халід Абгакмеlithuania_ municipalities. kgm's' HTMX. NET бібліотека надає можливість інтеграції ядра першого класу ASP. NET. Доступний як Htmx і Htmx.TagHelpers Пакунки NuGet, вони вважаються природними для .NET і роблять роботу з HTMX абсолютним задоволенням. GitHub.
dotnet add package Htmx
dotnet add package Htmx.TagHelpers
У вашій _ViewImports.cshtml:
@addTagHelper *, Htmx.TagHelpers
Найкориснішим є можливість Request.IsHtmx() Метод додавання, за допомогою якого ви можете визначити, чи було надіслано запит за допомогою HTMX. За допомогою цього способу ви можете повернути або повний перегляд, або лише частковий:
[HttpGet]
public async Task<IActionResult> Index(int page = 1, int pageSize = 20)
{
var posts = await blogViewService.GetPagedPosts(page, pageSize);
if (Request.IsHtmx())
return PartialView("_BlogSummaryList", posts);
return View("Index", posts);
}
Цей шаблон є абсолютно блискучим. Дії одного контролера слугують обом:
Нет разных основ API, никаких повторяющих логической логики, нет серифии ДЖСОН.
Поширене неправильне уявлення: Багато розробників ASP. NET вважають, що вам потрібен
_префікс (на зразок_BlogSummaryList.cshtml) щоб отримати частковий переклад.PartialView()Сам метод наказує ASP. NET Core пропустити компонування - він каже " забути розкладку, просто показати цей біт ." Ви можете скористатисяreturn PartialView("SearchResults", model)з звичайним файлом перегляду і він працює ідеально. Компіляція підкреслювання походила з веб- сторінок ASP. NET (WebMatrix), за допомогою якої програма запобігала показу файлів безпосередньо за допомогою адреси URL, - але MVC завжди захищав всі перегляди від прямого доступу. Це суто умова назви, яка допомагає визначати перегляди. намір як часткові.
У HTMX. NET передбачено допоміжні засоби для роботи з мітками, які роблять роботу з очищувачем регуляторів. Замість створення рядків маршрутів, ви можете скористатися добре визначеними посиланнями:
<button
hx-controller="Comment"
hx-action="GetCommentForm"
hx-post
hx-target="#commentform">
Reply
</button>
Ця програма створює правильний маршрут за допомогою системи маршрутизації ядра ASP. NET. Якщо ви перейменуєте регулятор або дію, ваш IDE його зловить. Значно краще ніж магічні рядки!
Ось приклад системи коментарів цього блогу:
<button
class="btn btn-outline btn-sm mb-4"
hx-action="Comment"
hx-controller="Comment"
hx-post
hx-vals
x-on:click.prevent="window.mostlylucid.comments.setValues($event)"
hx-on="htmx:afterSwap: window.scrollTo({top: 0, behavior: 'smooth'})"
hx-swap="outerHTML"
hx-target="#commentform">
Comment
</button>
Зауважте, як HTMX добре грає з альпійськими.js (x-on:click.prevent) для тих випадкових частин клієнтської взаємодії.
Крім того, у бібліотеці передбачено:
Request.IsHtmxNonBoosted() - Перевірте, чи є це запит HTMX, але не покращенийRequest.IsHtmxRefresh() - Перевірте, чи це запит на відновлення історії.Ось контролер пошуку з цього блогу, який показує шаблон повернення до трьох способів:
[HttpGet]
[OutputCache(Duration = 3600, VaryByHeaderNames = new[] { "hx-request", "pagerequest" })]
public async Task<IActionResult> Search(
string? query,
int page = 1,
int pageSize = 10,
[FromHeader] bool pagerequest = false)
{
var searchModel = await BuildSearchModel(query, page, pageSize);
if (pagerequest && Request.IsHtmx())
return PartialView("_SearchResultsPartial", searchModel.SearchResults);
if (Request.IsHtmx())
return PartialView("SearchResults", searchModel);
return View("SearchResults", searchModel);
}
Три шляхи повернення для трьох сценаріїв:
Частковий перегляд (_SearchResultsPartial.cshtml) використовує помічника відсилання міток:
@model Mostlylucid.Models.Blog.PostListViewModel
<div class="pt-2" id="content">
@if (Model.Data?.Any() is true)
{
<div class="inline-flex w-full items-center justify-center pb-4">
@if (Model.TotalItems > Model.PageSize)
{
<pager
x-ref="pager"
link-url="@Model.LinkUrl"
hx-boost="true"
hx-target="#content"
hx-swap="show:none"
page="@Model.Page"
page-size="@Model.PageSize"
total-items="@Model.TotalItems"
hx-headers='{"pagerequest": "true"}'>
</pager>
}
</div>
@foreach (var post in Model.Data)
{
<partial name="_ListPost" model="post"/>
}
}
</div>
Інструмент для обробки міток пейджера:
hx-boost="true" - Інтерцепти з'єднують, конвертують на AJAXhx-target="#content" - Де ввести відповідьhx-headers='{"pagerequest": "true"}' - Нетиповий заголовок вказує контролеру, що це загінRequest.IsHtmx() && pagerequest щоб повернути лише мінімальну частковістьЯ написав threelucid.pproginghelper Щоб уникнути коду періодичної пагінації. Спочатку це HTMX, але без JavaScript також працює.
dotnet add package mostlylucid.pagingtaghelper
Додати до _ViewImports.cshtml:
@addTagHelper *, mostlylucid.pagingtaghelper
Реалізація IPagingModel<T> І ви закінчили:
public class BasePagingModel<T> : IPagingModel<T> where T : class
{
public int Page { get; set; }
public int TotalItems { get; set; }
public int PageSize { get; set; }
public string LinkUrl { get; set; }
public List<T> Data { get; set; }
}
Що ви отримаєте:
Помічник теґів створює посилання, за допомогою яких можна зберігати рядки запитів, підтримувати нетипові заголовки та плавно об' єднуватися з HTMX (див. приклад, описаний вище).
Ось як уся система поєднується:
graph TB
A[Browser] -->|"Initial page load"| B[Controller Action]
B -->|"Request.IsHtmx() = false"| C[Return Full View]
C --> D[Render Layout + Partial]
A -->|"User clicks pagination/filter"| E[HTMX Request]
E -->|"hx-get with headers"| F[Same Controller Action]
F -->|"Request.IsHtmx() = true"| G{Check Headers}
G -->|"pagerequest header"| H[Return Minimal Partial]
G -->|"No special header"| I[Return Section Partial]
H --> J[Swap Content in Target]
I --> J
J -->|"User clicks another link"| E
style B stroke:#333,stroke-width:2px
style F stroke:#333,stroke-width:2px
style C stroke:#0066cc,stroke-width:2px
style H stroke:#00cc66,stroke-width:2px
style I stroke:#00cc66,stroke-width:2px
Django додав правильний шаблон відображення у версії 6. 0 (грудень 2024) з фрагментами шаблонів. Перед цим розробники Django зазвичай використовували мітки включення або пакунки третьої частини, на зразок django- block. ASP. NET Core мали ядро PartialView() починаючи з версії 1. 0 у 2016 році - різні оболонки, різні розклади, але те саме призначення: фрагменти HTML для HTMX.
Ruby on Rails має блоки Turbo (частину Hotwire), які подібні у дусі:
<%= turbo_frame_tag "posts" do %>
<%= render @posts %>
<% end %>
Різниця полягає в тому, що "Турбо" вимагає певних позначок кадрів як на запитах, так і на відповідь. HTMX більш гнучкий - будь-яка кінцева точка може повернути будь-який HTML, і ви вирішуєте, куди він йде. hx-target.
Elixir's Finix LiveView робить інший підхід з постійними з' єднаннями WebSocket і станом на стороні сервера:
def handle_event("load_more", _params, socket) do
{:noreply, assign(socket, posts: load_more_posts())}
end
LiveView є блискучим для програм у режимі реального часу, але для з' єднання потрібні інфраструктура WebSocket і пам' ять сервера. HTMX використовує звичайний старий HTTP - недоступний, придатний для кешування, придатний для масштабування. Для блогу це ідеально.
Кечування виводу: The OutputCache attribute міняється на hx-request заголовок, кешування сторінок і частинок окремо:
[OutputCache(Duration = 3600, VaryByHeaderNames = new[] { "hx-request", "pagerequest" })]
Network Efficiency: HTML, що виконується на сервері, часто менший за шаблон JSON + клієнтська сторона, потребує менше ходів і кешів належним чином.
Розмір м' ячика: HTMX (14KB) + необов' язкові альпійські. js (15KB) + linger tag assist (0KB, side) = 30KB загалом. Порівняйте це з типовою програмою React (200KB+).
Оптимістичне оновлення інтерфейсу користувача - З'єднайте HTMX і альпійські Альпи для миттєвого зворотній зв'язку:
<div x-data="{ count: @Model.CommentCount }">
<button hx-post="/comment/like" x-on:click="count++" hx-on::after-request="count = $event.detail.xhr.response">
Likes: <span x-text="count"></span>
</button>
</div>
Кількість оновлень негайно (оптимістичних), потім синхронізується з відповіддю сервера.
Свопінги поза комп' ютером - Оновити декілька розділів сторінки з однієї відповіді:
<div id="main-content"><!-- Main response --></div>
<div id="notification-count" hx-swap-oob="true"><span>5 new</span></div>
Ідеально для сповіщень, кілок карт тощо. Я зафарбую цей шаблон глибше Показ тоста і поміняння місцями з HTMX.
Шаблони клієнта з веб-API - Иногда вам нужен опыт в середине: посещенный по серверу HTML для большинства вещей, но JSON из веб-API для специальной динаміческой конфиденциальности HTMX. розширення client- side- templates Надає вам змогу зробити саме це:
<script src="https://unpkg.com/htmx-ext-client-side-templates@2.0.0/client-side-templates.js"></script>
<script src="https://unpkg.com/mustache@latest"></script>
<div hx-ext="client-side-templates">
<template id="post-template" type="text/mustache">
{{#posts}}
<div class="post">
<h3>{{title}}</h3>
<p>{{excerpt}}</p>
</div>
{{/posts}}
</template>
<button hx-get="/api/posts"
hx-target="#post-list"
mustache-template="post-template">
Load Posts
</button>
<div id="post-list"></div>
</div>
Цей підхід працює з шаблонами Mustche, processingbars або Nunjucks. Ваші WebAPI повертає JSON, але HTMX керує клієнтським інтерфейсом. Цей підхід особливо корисний, якщо у вас вже існує API або вам потрібно поділитися даними з мобільними програмами. Докладніше про розширення HTMX, зокрема шаблони клієнтської сторони, див. супутня стаття.
Інструмент зневаджування: Встановити Розширення зневадника HTMX - вона показує всі просьби, відповідь і обмінюються місцями в режимі реального часу.
У ядрах антиforgery ASP. NET потрібні особливі інструменти керування з AJAX. HTMX. NET передбачено декілька чистих параметрів. Рекомендований спосіб використання HtmxAntiforgeryScriptEndpoint:
// In Program.cs
app.MapHtmxAntiforgeryScript();
<!-- In your layout head -->
<script src="@HtmxAntiforgeryScriptEndpoints.Path" defer></script>
Або скористайтеся помічником теґів: <meta name="htmx-config" includeAspNetAntiforgeryToken="true" />. Див. Стаття Халіда про антикумерні тонки HTMX (англ.) за докладними деталями.
Альпійські гори @click Короткі конфлікти з Razor's @ Синтаксис. Замість цього використовуйте чітку форму:
<button x-on:click="doSomething()">Click me</button> <!-- Instead of @click -->
<div x-bind:class="isOpen ? 'block' : 'hidden'"></div> <!-- Instead of :class -->
Або втекти з @@click, але ясніший синтаксис.
Керування записами журналу: Типово, HTMX надсилає всі запити до журналу. За пагін/ фільтри, де ви не бажаєте забруднювати історію:
<paging model="@Model" hx-push-url="false"> <!-- Don't add history entries -->
Або скористатися hx-replace-url="true" щоб оновити адресу URL без додавання записів.
Фантомна проблема: Переглядач назад/ forward показує лише частковий фрагмент без компонування. Виправити за допомогою hx-history-elt у вашому контейнері вмісту:
<div class="container mx-auto" id="contentcontainer" hx-history-elt>
@RenderBody()
</div>
За допомогою цього пункту можна вказати HTMX, який елемент слід зняти, зберігаючи при відновленні історію компонування.
Сиптом: HTMX працює локально, але ламається після CDN - неправильний вміст буде кешовано.
Коренева причина: CDN проігнорується HX-Request заголовок. Ваш сервер повертає інший вміст, заснований на цьому заголовку, але кеш CDN зберігається ідентично.
Виправлення ядра ASP. NET: Користування VaryByHeaderNames:
[OutputCache(Duration = 3600, VaryByHeaderNames = new[] { "hx-request" })]
Виправлення CDN: Налаштування правил кешу для включення HX-Request у ключі кешу. Для Harhaflare: Dashboard → Caching → Правила кешу → Нетиповий ключ кешу → Заголовки → Включати HX-Request.
hx-boost Перетворює звичайні посилання на запити AJAX. Сторінка Природоохоронців HTMX замітка, деякі члени команди рекомендують уникати цього (discards <head> Зміст, впливає на місцеву поведінку), тоді як інші кажуть, що це добре для скорої перемоги.
<div hx-boost="true" hx-target="#contentcontainer">
<a asp-action="Show" asp-route-slug="@post.Slug">Read More</a>
</div>
Цей блог широко використовує його. Під час наповнення специфічних контейнерів, явне використання hx-get зрозуміліше, але hx-boost працює, якщо ви послідовні. Вимкніть вибірково з hx-boost="false" про дитячі елементи.
HTMX з частинками ядра ASP. NET є поверненням до простоти з боку сервера без жертвування сучасного UX. Ви можете отримати:
Підхід до сервера пройшов перевірку часом, і за допомогою HTMX, нарешті, у нього є елегантний клієнтський інструмент на його боці. Ви можете будувати міцні, виконувані веб- програми за допомогою шаблонів, які десятиліттями працювали, - вони просто чекали на потрібні інструменти, щоб зробити їх знову світлішими.
Ця стаття є частиною двосторонньої серії HTMX з ядром ASP. NET:
Офіційна документація:
& Інструменти бібліотек:
Ресурси спільноти:
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.