如何为网站菜单搜索功能实现A-Z字母排序?
问题
我的网站有带子菜单的菜单系统,已经实现全局菜单搜索功能,用户输入内容时会逐步筛选匹配结果,但当前搜索结果未按A-Z字母排序。比如输入字符h时,返回结果是:
Watch Hate Hates
输入字符a后,返回结果是:
Hates Hate
我希望搜索结果能按A-Z字母顺序排列,该怎么实现?
以下是当前实现的代码:
HTML代码
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <section class="app"> <aside class="sidebar"> <nav class="sidebar-nav"> <input type='text' id='search' value='' /> <ul id='menu'> <li> <a href="#"><i class="ion-bag"></i> <span>Shop</span></a> <ul class="nav-flyout"> <li> <a href="#" class='link' data-link='page1'><i class="ion-ios-color-filter-outline"></i>Derps</a> </li> <li> <a href="#" class='link' data-link='page2'><i class="ion-ios-clock-outline"></i>Times</a> </li> <li> <a href="#" class='link' data-link='page3'><i class="ion-android-star-outline"></i>Hates</a> </li> <li> <a href="#" class='link' data-link='page4'><i class="ion-heart-broken"></i>Beat</a> </li> </ul> </li> <li> <a href="#"><i class="ion-ios-settings"></i> <span class="">Controls</span></a> <ul class="nav-flyout"> <li> <a href="#" class='link' data-link='page5'><i class="ion-ios-alarm-outline"></i>Watch</a> </li> <li> <a href="#" class='link' data-link='page6'><i class="ion-ios-camera-outline"></i>Creeper</a> </li> <li> <a href="#" class='link' data-link='page7'><i class="ion-ios-chatboxes-outline"></i>Hate</a> </li> <li> <a href="#" class='link' data-link='page8'><i class="ion-ios-cog-outline"></i>Grinder</a> </li> </ul> </li> <li> </ul> </nav> </aside> </section>
CSS代码
@import "bourbon"; @import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,300,600); body { font-family: "Lato"; font-size: 100%; overflow-y: scroll; font-family: sans-serif; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; background-color: #fefefe; } a { text-decoration: none; @include transition(all 0.6s ease); &:hover { @include transition(all 0.6s ease); } } .app { height: 100vh; } /* ------------- Sidebar ----------------*/ .sidebar { position: absolute; //width: 33.3333%; width: 17em; height: 100%; top: 0; overflow: hidden; background-color: #19222a; -webkit-transform: translateZ(0); visibility: visible; -webkit-backface-visibility: hidden; header { background-color: #09f; width: 100%; display: block; padding: 0.75em 1em; } } /* ------------- Sidebar Nav ----------------*/ .sidebar-nav { position: fixed; //width: 13em; background-color: #19222a; height: 100%; font-weight: 400; font-size: 1.2em; overflow: auto; padding-bottom: 6em; z-index: 9; overflow: hidden; -webkit-overflow-scrolling: touch; ul { list-style: none; display: block; padding: 0; margin: 0; li { margin-left: 0; padding-left: 0; //min-width: 13em; display: inline-block; width: 100%; a { color: rgba(255, 255, 255, 0.9); font-size: 0.75em; padding: 1.05em 1em; position: relative; display: block; &:hover { background-color: rgba(0, 0, 0, 0.9); @include transition(all 0.6s ease); } } /* ------------- Sidebar: icons ----------------*/ i { font-size: 1.8em; padding-right: 0.5em; width: 9em; display: inline; vertical-align: middle; } } } /* ------------- Chev elements ----------------*/ &>ul>li>a:after { content: '\f125'; font-family: ionicons; font-size: 0.5em; width: 10px; color: #fff; position: absolute; right: 0.75em; top: 45%; } /* ------------- Nav-Flyout ----------------*/ & .nav-flyout { position: absolute; background-color: #080D11; z-index: 9; left: 2.5em; top: 0; height: 100vh; @include transform(translateX(100%)); @include transition(all 0.5s ease); a:hover { background-color: rgba(255, 255, 255, 0.05) } } /* ------------- Hover ----------------*/ & ul>li:hover { .nav-flyout { @include transform(translateX(0)); @include transition(all 0.5s ease); } } }
JavaScript代码
menu = $('#menu').html() $("body").on('keyup', '#search', function(e) { searchfor = $(this).val() if (searchfor.length > 0) { $('#menu li').hide() $('.link').each(function(i, obj) { if (obj.text.search(new RegExp(searchfor, 'i')) > -1) { $('#menu').prepend($(this).closest('li').show()) } }) } else { $('#search').val('') $('#menu li').show() $('#menu').empty().append(menu) } })
解决方案
要实现搜索结果按A-Z排序,需要先收集所有匹配的元素,对它们的文本内容进行排序后再添加到菜单中,而不是找到一个就直接插入。具体修改步骤如下:
- 创建数组存储所有匹配的元素及其文本内容
- 使用
localeCompare方法对数组按文本内容进行不区分大小写的排序 - 清空菜单后,将排序后的元素依次添加进去
修改后的JavaScript代码如下:
const menu = $('#menu').html(); $("body").on('keyup', '#search', function(e) { const searchfor = $(this).val().trim(); if (searchfor.length > 0) { $('#menu li').hide(); const matches = []; $('.link').each(function() { const text = $(this).text().trim(); if (text.search(new RegExp(searchfor, 'i')) > -1) { matches.push({ text: text.toLowerCase(), element: $(this).closest('li') }); } }); // 按文本内容A-Z排序 matches.sort((a, b) => a.text.localeCompare(b.text)); // 清空菜单并添加排序后的元素 $('#menu').empty(); matches.forEach(item => { $('#menu').append(item.element.show()); }); } else { $('#search').val(''); $('#menu').empty().append(menu).find('li').show(); } });
修改说明
- 新增
matches数组,存储每个匹配项的文本(转小写用于排序)和对应的DOM元素 - 使用
localeCompare进行排序,确保排序结果符合自然语言的字母顺序,且不区分大小写 - 先清空菜单,再将排序后的元素依次添加,避免原顺序影响结果
- 对
searchfor做了trim()处理,避免空格导致的无效搜索
修改后,输入h时会返回按A-Z排序的结果:
Hate Hates Watch
输入a时返回:
Hate Hates
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

