Back to "ASP.NET核心项目类似SP.NET经验的HTMX(和一点阿尔卑斯山)"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

ASP.NET HTMX Apline.js

ASP.NET核心项目类似SP.NET经验的HTMX(和一点阿尔卑斯山)

Sunday, 15 September 2024

一. 导言 导言 导言 导言 导言 导言 一,导言 导言 导言 导言 导言 导言

我用这个网站 HTMX 广度而言,这是一个非常容易的方法 让你的网站感到更灵敏 更顺畅 不需要写很多 JavaScript 。

注意:我还不完全满意,HTMX 有一些因素使这个过程变得棘手

HTMX和ASP.NET核心

使用 HTMX 与 ASP. NET Core 使用 HTMX 与 ASP. 此员额.. 使用“HTMXififify”网站非常容易, 这是让网站感觉更灵敏的好方法。

普通链接

作为我最近使用HTMX I 环绕一圈的一部分, 决定让这个网站尽可能多的链接尽可能使用HTMX。 例如,如果您单击上面的“ 家” 按钮, 现在使用 HTMX 来装入页面内容 。

我只需在链接标签上添加一些属性,

    <a asp-action="IndexPartial" asp-controller="Home" hx-swap="show:window:top"  hx-target="#contentcontainer" hx-boost="true" class="mr-auto sm:mr-6">
     <div class="svg-container">
        <img src="/img/logo.svg" asp-append-version="true"  width="180px" height="30px"  alt="logo"  :class="{ 'img-filter-dark': isDarkMode }"/>
     </div>
    </a>

在这里,你可以看到,我添加 hx-swap 属性, 这将告诉 HTMX 将目标元素的内容与服务器上返回的内容互换 。

注意: 不要使用 hx- pushurl, 因为这会使浏览器在后端按钮上重新装入页面两次 。

缩略 hx-target 属性 告诉 HTMX 将从服务器返回的内容放在哪里 。 在这种情况下,这是 #contentcontainer 元素(所有页面内容都已装入) 。

我还补充补充: hx-swap="show:window:top 使窗口滚动到页面顶部,当内容被交换时。

C # 部分很简单, 它只是重复我的正常索引方法, 而是加载部分视图 。 代码显示如下。 再次使用此用途 HTMX.NET 以探测 hx-request 页眉并返回部分视图。 如果请求不是 HTMX 请求, 还需要截断以回复正常视图 。

    [Route("/IndexPartial")]
    [OutputCache(Duration = 3600, VaryByHeaderNames = new[] { "hx-request" })]
    [ResponseCache(Duration = 300, VaryByHeader = "hx-request",
        Location = ResponseCacheLocation.Any)]
    [HttpGet]
    public async Task<IActionResult> IndexPartial()
    {
        ViewBag.Title = "mostlylucid";
        if(!Request.IsHtmx()) return RedirectToAction("Index");
        var authenticateResult = await GetUserInfo();
        var posts = await BlogService.GetPagedPosts(1, 5);
        posts.LinkUrl = Url.Action("Index", "Home");
     
        var indexPageViewModel = new IndexPageViewModel
        {
            Posts = posts, Authenticated = authenticateResult.LoggedIn, Name = authenticateResult.Name,
            AvatarUrl = authenticateResult.AvatarUrl
        };
        return PartialView("_HomePartial", indexPageViewModel);
    }

其结果是,这种链接(和其他使用相同技术的链接)的负荷与“AJAX”要求的负荷相同,而内容在没有全页重新加载的情况下被互换。 这避免了当页面因我的主题转换方式而重新加载时你得到的令人烦恼的“ 闪光” 。

博客链接(简单方式)

因此,下面的方法可以做成 工作,不管它是如何的 超级棘手和有点尴尬。 HTMX 确实喜欢使用基于属性的方法工作 。 使用 htmx.ajax 是一种“ 如果所有其他方法都失败了” 的方法, 意味着你需要与 Borwser 历史打交道。 不幸的是浏览器历史使用 pushState replaceStatepopstate 颈部确实有点疼(但对于边缘病例则具有超强的威力)。

而不是我现在所做的 只是添加 hx-boost 上包含博客内容的标签。

   <div class="prose prose max-w-none border-b py-2 text-black dark:prose-dark sm:py-2" hx-boost="true"  hx-target="#contentcontainer">
        @Html.Raw(Model.HtmlContent)
    </div>

这似乎效果良好 hx-boost 可采用家长方法,并适用于所有与儿童的联系。 更普通的HTMX,

在您不想使用 HTMX 作为特定链接的罕见场合中, 您可以添加 hx-boost="false" 链接.

博客链接(NOTE:我放弃了这个方法,

我的博客连结就像这个: 用于SPA类似经验的HTMX HTMX 它们不是“正常”链接。 这些链接是由标记分析器生成的; 虽然我可以写入一个 MarkDig 扩展名, 将 HTMX 属性添加到链接中, 我决定使用不同的方法( 因为我已经有一吨的内容我不想重复) 。

相反,我添加了一个 JavaScript 函数, 寻找所有这些类型的链接, 然后使用 htmx.ajax 做交换。 这基本上就是HTMX的工作,反正只是“手动”而已。

正如你可以看到的,这只是一个简单的函数,它寻找所有链接 div.prose 元素的元素,该元素以 / 然后,在他们之间,增加一个倾听者。 当单击链接时, 当单击链接时, 事件被阻止, URL会被提取, 然后 htmx.ajax 函数被调用为 URL 和要更新的目标元素。

(function(window) {
   
    window.blogswitcher =() =>  {
        const blogLinks = document.querySelectorAll('div.prose  a[href^="/"]');

        // Iterate through all the selected blog links
        blogLinks.forEach(link => {
            link.addEventListener('click', function(event) {
               event.preventDefault();
                let link = event.currentTarget;
                let url = link.href;
                htmx.ajax('get', url, {
                    target: '#contentcontainer',  // The container to update
                    swap: 'innerHTML',            // Replace the content inside the target


                }).then(function() {
                    history.pushState(null, '', url);
                  
                        window.scrollTo({
                            top: 0,
                            behavior: 'smooth' // For a smooth scrolling effect
                        });
                    
                });
            });
        });
        
    };
})(window);

此外,一旦进行了交换,我就会将新的 URL 推到浏览器历史中,然后滚动到页面的顶部。 我在几个地方(如搜索)使用这个方法,

返回按钮( 难以工作 )

这种应用程序的后端按钮可能有问题; 许多“ 正确” 的 SPA 要么禁用后端按钮, 要么 忍受这种不正确的行为 。 但我还是想确保后键能如预期的那样工作 注意: 要让后按钮如预期的那样工作, 我们也需要监听 popState 事件 。 当用户在浏览器历史中向后或向后导航时,此事件就会被启动 。 @ info: whatsthis 当此事件被启动时, 我们可以重新装入当前 URL 的内容 。

window.addEventListener("popstate",   (event) => {
 // When the user navigates back, reload the content for the current URL
 event.preventDefault();
 let url = window.location.href;
 // Perform the HTMX AJAX request to load the content for the current state
 htmx.ajax('get', url, {
  target: '#contentcontainer',
  swap: 'innerHTML'
 }).then(function () {
  // Scroll to the top of the page
  window.scrollTo({
   top: 0,
   behavior: 'smooth'
  });
 });
});

在此代码中, 我们防止默认浏览器 Pop state 行为 event.preventDefault() 拨打。 然后我们从当前 URL 中提取当前 URL window.location.href 属性,并执行 HTMX AJAX 请求,为当前状态装入内容。 一旦内容被装入,我们就滚动到页面的顶部。

如前所述,您不能使用 hx-pushurl 因为这将使浏览器在后端按钮上重新装入页面两次 。

较一般的HTMX(和阿尔卑斯山)

正如你可能猜想的,我有点喜欢HTMX, 加上ASP.NET Core 和Alpine.js的商品, 它赋予Devs权力, 创造出一个非常好的用户经验, 我比较喜欢更“完全形成”的客户侧框架, 如反应/角等, 主要是它仍然给我一个完整的服务器侧面, 与 ASP. NET Core 连接管道, 但与 SPA 的“感觉” 。 Alpine.js 使客户端的交互活动简单化, 最近我添加了一个非常简单的功能, 使我的分类“ 隐藏 ”, 但放大了点击 。

使用 Alpine.js 表示不需要额外的 JavaScript 。

        <div class="mb-8 mt-6 border-neutral-400 dark:border-neutral-600 border rounded-lg" x-data="{ showCategories: false }">
            <h4 
                class="px-5 py-1 bg-neutral-500  bg-opacity-10 rounded-lg  font-body text-primary dark:text-white w-full flex justify-between items-center cursor-pointer"
                x-on:click="showCategories = !showCategories"
            >
                Categories
                <span>
                    <i
                        class="bx text-2xl"
                        :class="showCategories ? 'bx-chevron-up' : 'bx-chevron-down'"
                    ></i>
                </span>
            </h4>
            <div 
                class="flex flex-wrap gap-2 pt-2 pl-5 pr-5 pb-2"
                x-show="showCategories" 
                x-cloak
                x-transition:enter="max-h-0 opacity-0"
                x-transition:enter-end="max-h-screen opacity-100"
                x-transition:leave="max-h-screen opacity-100"
                x-transition:leave-end="max-h-0 opacity-0"
            >
                @foreach (var category in ViewBag.Categories)
                {
                    <partial name="_Category" model="category"/>
                }
           
            </div>
        </div>

在这里,你可以看到,我用 x-data 属性以创建新的 Alpine.js 数据对象 showCategories.. 这是一个布尔,当 h4 元素被单击。 缩略 x-on:click 属性用于将单击事件绑绑到 TOGle 函数上。

在I类清单中,然后使用 x-show 属性,以显示或隐藏基于 showCategories.. 我也使用 x-transition 属性,以在显示或隐藏类别时添加一个漂亮的幻灯片向下效果。 缩略 x-cloak 属性属性 用于防止 JavaScript 运行前显示的类别中的“ flicker ” 。 我有一个小 CSS 类为此定义:

[x-cloak] { display: none !important; }

在结论结论中

因此,这就是关于如何使用HTMX的短篇文章, 以及阿尔卑斯山的一处地方, 如果有任何问题或评论,请将问题或评论留在下面。

logo

©2024 Scott Galloway