使用 SortableJS 组件的 Blazor 可排序列表

Web 应用程序的一个常见功能是可排序列表。SortableJS是我最喜欢的 JavaScript 库之一,在使用 Blazor 开发时我错过了它。为了解决这个问题,我决定包装 SortableJS 使其成为 Blazor 组件,名为Bazor Sortable,我已在 GitHub 上开源了它,我认为您会喜欢的。在这篇文章中,我将引导您了解如何将其添加到您自己的 Blazor Web 应用程序中。

注意:Blazor Sortable 是一个开源社区组件,而不是 Microsoft 的官方组件。Fluent UI for Blazor 团队为 Fluent UI for Blazor 集成了一个可排序组件。您今天可以尝试Fluent UI Sortable Demo

在这里查看演示: https: //blazorsortable.theurlist.com

每个星期五,Jon Galloway(你从未听说过他,但他是值得信赖的人)和我致力于在 Blazor 中重建一个名为theurlist.com的真实应用程序。该直播在 Twitch 和 .NET YouTube 上被称为“ Burke Learns Blazor ”(点赞并订阅!)。我们很高兴您加入我们。主要是因为我们需要所有可以得到的帮助来处理这件事,因为我不知道我在做什么。

我们最终需要一个可排序列表组件来进行此重建,虽然有一些“Blazor Sortable”示例,但我还是很喜欢SortableJS。SortableJS 是一个出色的库,用于构建可排序的项目列表,几乎具有您可能需要的所有功能 - 排序、列表之间的排序、克隆项目、过滤、自定义动画缓动、腰部支持。好吧——不是最后一个,但那就是,这是它唯一没有的东西。

因此,在 Steve Sanderson 的帮助下,我们在 SortableJS 上构建了一个简单的抽象,您可以将其放入您自己的应用程序中并使用。让我们看一下如何为您自己的 Blazor 应用使用和自定义 Blazor Sortable。

使用 Blazor 可排序

Blazor Sortable 的 GitHub 存储库包含可排序列表的源代码以及演示。对于您自己的项目,您只需要Shared/SortableList.razor,Shared/SortableList.razor.cssShared/SortableList.razor.js文件。

SortableList组件是一个通用组件,它接受项目列表并SortableItemTemplate定义如何呈现可排序列表中的每个项目。例如,假设您有一个如下所示的书籍列表......

public class Book
{
    public string Title { get; set; } = "";
    public string Author { get; set; }  = "";
    public int Year { get; set; }
}

public List<Book> books = new List<Book>
{
    new Book { Title = "The Very Hungry Caterpillar", Author = "Eric Carle", Year = 1969 },
    new Book { Title = "Where the Wild Things Are", Author = "Maurice Sendak", Year = 1963 },
    new Book { Title = "Goodnight Moon", Author = "Margaret Wise Brown", Year = 1947 },
    new Book { Title = "The Cat in the Hat", Author = "Dr. Seuss", Year = 1957 },
    new Book { Title = "Charlotte's Web", Author = "E.B. White", Year = 1952 },
    new Book { Title = "Harry Potter and the Sorcerer's Stone", Author = "J.K. Rowling", Year = 1997 },
    new Book { Title = "The Lion, the Witch and the Wardrobe", Author = "C.S. Lewis", Year = 1950 },
    new Book { Title = "Matilda", Author = "Roald Dahl", Year = 1988 },
    new Book { Title = "The Giving Tree", Author = "Shel Silverstein", Year = 1964 },
    new Book { Title = "Oh, the Places You'll Go!", Author = "Dr. Seuss", Year = 1990 }
};

您可以像这样呈现此列表SortableList...

<div>
    <SortableList Items="books" Context="book">
        <SortableItemTemplate>
            <div class="book">
                <p>@book.Title</p>
            </div>
        </SortableItemTemplate>
    </SortableList>
</div>

SortableList组件将使用 渲染项目列表SortableItemTemplate,然后使用 SortableJS 使列表可排序。该Context参数用于定义变量的名称,该变量将用于表示列表中的每个项目。在本例中,Contextis book,因此列表中的每个项目都将由一个名为 的变量表示book

但是,如果您此时尝试拖放项目,您会注意到每当您放下一个项目时,它就会回到之前的位置。那是因为我们没有告诉SortableList列表排序后要做什么。我们通过自己处理OnUpdate事件并进行排序来做到这一点。

<div>
    <SortableList Items="books" Context="book" OnUpdate="@SortList">
        <SortableItemTemplate>
            <div class="book">
                <p>@book.Title</p>
            </div>
        </SortableItemTemplate>
    </SortableList>
</div>
...
public void SortList((int oldIndex, int newIndex) indices)
{
    // deconstruct the tuple
    var (oldIndex, newIndex) = indices;

    var items = this.books;
    var itemToMove = items[oldIndex];
    items.RemoveAt(oldIndex);

    if (newIndex < items.Count)
    {{
        items.Insert(newIndex, itemToMove);
    }}
    else
    {{
        items.Add(itemToMove);
    }}
}

OnUpdate每当列表排序时,都会调用事件处理程序。它将传递一个包含已移动项目的旧索引和新索引的元组。在该SortList方法中,我们将元组解构为两个变量,然后使用它们来移动列表中的项目。

永远不要改变 Blazor 控制的 DOM,这一点非常重要。Blazor 保留 DOM 的内部副本,如果您使用 JavaScript 等内容更改它,您将得到奇怪的结果,因为页面状态将与 Blazor 的内部状态不同步。因此,我们在幕后所做的就是取消 JavaScript 移动,以便该项目实际上不会在页面上移动。然后我们移动列表中的项目,Blazor 将按照新顺序重新渲染列表。

一个更复杂的例子

SortableJS 是一个非常强大的库,它不仅仅可以对列表进行排序。它还可以在列表之间排序、克隆项目、过滤项目等等。该SortableList组件支持其中许多功能。让我们看一个更复杂的例子——两个列表之间的排序……

<div>
    <div class="container">
        <div class="columns">
            <div class="column">
                <h3>Books</h3>
                <SortableList Items="books" Context="book" OnRemove="@AddToFavoriteList" Group="favorites">
                    <SortableItemTemplate>
                        <div class="book">
                            <p>@book.Title</p>
                        </div>
                    </SortableItemTemplate>
                </SortableList>
            </div>
            <div class="column">
                <h3>Favorite Books</h3>
                <SortableList Items="favoriteBooks" Context="book" OnRemove="@RemoveFromFavoriteList" Group="favorites">
                    <SortableItemTemplate>
                        <div class="book">
                            <p>@book.Title</p>
                        </div>
                    </SortableItemTemplate>
                </SortableList>
            </div>
        </div>
    </div>
</div>

在此示例中,我们有两个列表 - 所有书籍的列表和最喜欢的书籍的列表。它们通过属性连接在一起Group

我们希望能够将书籍从所有书籍列表拖放到最喜欢的书籍列表中。为此,我们需要处理OnRemove两个列表的事件。

public void AddToFavoriteList((int oldIndex, int newIndex) indices)
{
    var (oldIndex, newIndex) = indices;

    var book = books[oldIndex];
    favoriteBooks.Insert(newIndex, book);
    books.RemoveAt(oldIndex);
}

public void RemoveFromFavoriteList((int oldIndex, int newIndex) indices)
{
    var (oldIndex, newIndex) = indices;

    var book = favoriteBooks[oldIndex];
    books.Insert(newIndex, book);
    favoriteBooks.RemoveAt(oldIndex);
}

链接在一起的多个列表的屏幕截图,图像

设置 SortableList 的样式

默认情况下,SortableList包含一些默认样式,在拖动时隐藏“幽灵”元素。当您拖动时,这会给您带来项目之间的间隙。如果没有这种样式更改,项目本身将显示为放置目标。这有点奇怪,因为这意味着您正在拖动的项目也是您要放置的项目。但如果这就是您的想法,您可以覆盖文件中的样式SortableList.razor.css,或者根本不包含它。

由于在 a 内呈现的所有内容SortableList都会在子级内呈现SortableItemTemplate,因此您始终必须使用“::deep”修饰符才能使任何更改生效。

SortableList如果您从父页面/组件(即 Index.razor.css)设置样式,则必须将其包装SortableList在容器元素中,并使用“::deep”修饰符。如果你不这样做,你的样式将不会生效,你会因为我制作这个组件而感到悲伤、困惑和生气。这是 Blazor 的事情,而不是 SortableJS 的事情。您可以在ASP.NET Core 文档中阅读有关范围样式的更多信息。

我觉得没有人会读最后一段,并且会有很多哀号和咬牙切齿的声音。但我尝试过。提前抱歉。

为什么不使用 HTML5 拖放?

这是一个公平的问题,也是我在使用 JavaScript 解决方案之前确实研究过的一个问题。总而言之,原生 HTML5 对拖放的支持对于像样的排序来说不够强大。例如,无法对大部分拖放行为进行样式化。它看起来……愚蠢……而且你对此无能为力。它对跨浏览器的支持也很不稳定。有一些基本属性仅适用于 Chrome。

综上所述,SortableJS 实际上会尝试在 iOS 等平台上使用 HTML5 拖放和回退到 JavaScript 解决方案。但是,您仍然无法控制样式,并且会出现看起来愚蠢的拖放操作。所以我SortableList如果您想重新打开它,请进入该SortableList.razor.razor.js文件并删除该forceFallback: true属性。我可能应该在某个时候将其作为一个设置。

获取 Blazor 可排序

查看Blazor Sortable并告诉我们您的想法!您可以用它做很多事情,包括克隆项目、禁用某些项目的排序、指定拖动手柄等等。我们还没有实现 SortableJS 的每一个功能。然而。欢迎拉取请求!

Blazor Sortable 是一个开源社区项目。

文章作者 | Burke Holland(伯克·霍兰德)

  • 26
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值