flexbox:1.0.0
在本文中,我们将逐步学习如何构建一个简单的jQuery插件,该插件根据其自定义数据属性的值对元素进行排序。
如果您对最终结果感到好奇,请查看相应的CodePen演示:
请参阅用于在CodePen上按SitePoint( @SitePoint )对元素进行排序的Pen Simple jQuery插件 。
注意:本文假定您对flexbox有基本的了解,以及如何开发jQuery插件 。 如果您不熟悉这些主题,请务必查看链接。
可达性问题
要构建我们的插件,我们将利用flexbox的功能。
默认情况下,弹性项目根据其源顺序进行布局。 但是,通过使用order属性,我们可以在父级flex容器内更改其顺序。 具有较低order
值的项目将首先出现。 请参阅以下示例:
见笔Flexbox的的“命令”属性由SitePoint( @SitePoint上) CodePen 。
如果有多个具有相同order
值的商品,则这些商品的订单取决于其来源顺序。
尽管order
属性使我们可以轻松地对元素进行重新排序,但它具有可访问性限制:它在源顺序和可视顺序之间造成了脱节。 为了更好地理解该问题,请查看本文 (尤其是“源顺序与视觉顺序”部分)。
因此,在继续研究如何构建我们的插件之前,请注意,它将无法访问。
标记
首先,我们定义一个具有十二个列表项的无序列表:
<ul class="boxes">
<li>
<a href="#">
Box1
<div class="details">
<span class="length">13M</span>
<span class="price">670€</span>
</div>
</a>
</li>
<!-- more list items here -->
</ul>
请注意,在每个列表项中都有一个.details
元素,该元素显示有关相应项的一些信息。 稍后我们将看到,我们还将添加自定义HTML属性来存储此信息。
注意:
.details
元素并不是必需的。 我们仅使用它来更好地了解目标元素的排序方式。
接下来,我们确定要排序的属性。 在我们的项目中,这些是price
和length
属性。 考虑到这一点,我们使用它们的名称将自定义属性( data-price
和data-length
)应用于列表项。 这些属性的值匹配的文本值(只有数字) .length
和.price
元件,其是一部分.details
元件。
例如,以下是第一个列表项的属性:
<li data-length="13" data-price="670">
<a href="#">
Box1
<div class="details">
<span class="length">13M</span>
<span class="price">670€</span>
</div>
</a>
</li>
此时,我们指定负责对列表项进行排序的元素。 我们使用<select>
元素执行此操作:
<select class="b-select">
<option disabled selected>Sort By</option>
<option data-sort="price:asc">Price Ascending</option>
<option data-sort="price:desc">Price Descending</option>
<option data-sort="length:asc">Length Ascending</option>
<option data-sort="length:desc">Length Descending</option>
</select>
免费学习PHP!
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
如您所见,所有<option>
元素(第一个元素除外)都包含data-sort
属性。 此属性的值使用以下约定:
<option data-sort="price:asc">
因此,作为值,我们具有要排序的属性,后跟冒号以及“ asc”或“ desc”指示符。
CSS样式
准备好标记后,让我们向页面添加一些基本样式。 具体来说,我们将无序列表定义为flex容器,并将列表项的width: 25%
。 以下是相关CSS规则:
.boxes {
display: flex;
flex-wrap: wrap;
}
.boxes li {
width: 25%;
}
构建插件
我们将我们的插件numericFlexboxSorting
。 在显示构建过程之前,我们先从结局开始,并说明如何初始化它。
初始化插件
通常,插件应按以下方式初始化:
$("your-select-tag").numericFlexboxSorting();
例如,在我们的例子中:
$(".b-select").numericFlexboxSorting();
默认情况下,插件将使用.boxes li
类对元素进行排序。 我们可以通过更改elToSort
配置属性的值来覆盖此行为:
$(".b-select").numericFlexboxSorting({
elToSort: "the-elements-you-want-to-sort"
});
步骤分解
现在我们准备描述开发过程!
第一步,我们通过numericFlexboxSorting
添加numericFlexboxSorting
方法来扩展jQuery的原型( $.fn
)对象:
$.fn.numericFlexboxSorting = function() {
const $select = this;
// do stuff here
return $select;
};
在该方法中, this
关键字引用我们的<select>
元素。 创建插件后,我们必须返回此元素。 如果我们不这样做,方法链接将无法工作。
考虑以下代码,例如:
$(".b-select").numericFlexboxSorting().css("background", "red");
在这里,除非我们返回目标元素,否则css方法将不会执行任何操作。
正如我们已经提到的,默认情况下,该插件将使用.boxes li
类对元素进行排序。 但是,如果需要,我们应该能够覆盖此行为。 为了实现这一点,我们利用了jQuery的extend方法:
$.fn.numericFlexboxSorting = function(options) {
const settings = $.extend({
elToSort: ".boxes li"
}, options);
// do stuff here
};
该插件将按升序或降序对数字进行排序。 考虑到这一点,我们定义了相应的变量,稍后我们将使用它们:
$.fn.numericFlexboxSorting = function(options) {
const ascOrder = (a, b) => a - b;
const descOrder = (a, b) => b - a;
// do stuff here
};
一旦用户从下拉列表中选择一个选项(第一个选项除外),我们就应该检索并评估其值。 为此,我们使用change事件:
$.fn.numericFlexboxSorting = function(options) {
const $select = this;
$select.on("change", () => {
const selectedOption = $select.find("option:selected").attr("data-sort");
sortColumns(settings.elToSort, selectedOption);
});
// do stuff here
};
在事件处理程序内部,我们做两件事:
- 检索所选选项的
data-sort
属性的值(例如price:asc
)。 - 调用
sortColumns
函数。
sortColumns
函数接受两个参数:
- 我们要排序的元素。
- 所选选项的
data-sort
属性的值。
这是此函数的主体:
function sortColumns(el, opt) {
const attr = "data-" + opt.split(":")[0];
const sortMethod = (opt.includes("asc")) ? ascOrder : descOrder;
const sign = (opt.includes("asc")) ? "" : "-";
// 1
const sortArray = $(el).map((i, el) => $(el).attr(attr)).sort(sortMethod);
// 2
for (let i = 0; i < sortArray.length; i++) {
$(el).filter(`[${attr}="${sortArray[i]}"]`).css("order", sign + sortArray[i]);
}
}
让我们解释一下里面发生了什么:
根据用户想要排序的属性(即
price
或length
),我们为每个目标元素获取相关data-* attribute
的值,并将其存储在数组中。 另外,根据用户想要对目标元素进行排序的方式,我们以升序或降序对数组进行排序。-
我们遍历数组,找到相关元素,并为它们分配一个
order
属性值(正值或负值),该值由其相应的data-* attribute
的值确定。
因此,例如,如果用户选择price:asc
选项,则data-price: 315
的元素将收到order: 315
。另一方面,如果用户选择
price:desc
选项,它将收到order: -315
。
最后,为了防止与使用$
变量的其他库可能发生冲突,我们将代码包装在立即调用的函数表达式中,如下所示:
(function($) {
$.fn.numericFlexboxSorting = function(options) {
// do stuff here
};
})(jQuery);
我们的插件已准备就绪。 您可以在以下Codepen演示中实时看到它:
请参阅用于在CodePen上按SitePoint( @SitePoint )对元素进行排序的Pen Simple jQuery插件 。
插件限制
在这一点上,我们不得不回想起我们的插件有一个很大的限制:它不可访问。 为了证明这一点,请从下拉列表中选择一个选项,然后使用键盘( 单击笔并单击 “ Tab”键 )来浏览链接。 注意,元素根据其DOM顺序而不是 CSS顺序集中。
需要注意的另一件事是,该插件仅提供基本功能,因此只能在特定条件下使用。 例如,属性值字符串应仅包含数字值。 请记住,此值指定目标元素的order
(期望数字)。
显然,对于元素的排序和过滤,还有更可靠,更强大的库,如下所示:
特别是对于MixItUp,有一篇SitePoint文章介绍了它的基本知识。
浏览器支持
该插件取决于flexbox,因此其支持取决于浏览器的flexbox支持。 令人高兴的是,如今,flexbox具有出色的浏览器支持。
下一步
如果您喜欢挑战并想丰富此插件的功能,则可以执行以下操作:
添加对随机排序的支持。
-
提供给用户选择排序控件是
<select>
元素,许多<button>
元素还是其他控件类型的选项。 对于这种情况,您可能需要提供其他设置,例如:$(".b-select").numericFlexboxSorting({ elToSort: "the-elements-you-want-to-sort", controls: { select: true, // fires change event button: false // fires click event } });
结论
在本文中,我们经历了创建jQuery插件的过程。 该插件利用flexbox的功能,根据其自定义数据属性的值对元素进行排序。
您如何看待:将来您会用到这种东西吗? 您是否考虑过将JavaScript和flexbox结合的其他方式? 在评论中让我知道。
翻译自: https://www.sitepoint.com/user-sortable-lists-flexbox-jquery/
flexbox:1.0.0