搜索组件优化 - Command ⌘K

news/2024/11/15 6:57:22/文章来源:https://www.cnblogs.com/LaughingZhu/p/18395521

前言:

DevNow 项目中我们使用了 DocSearch 来实现搜索功能,但是由于有以下的限制:

  1. 您的网站必须是技术文档或技术博客。
  2. 您必须是网站的所有者,或者至少具有更新其内容的权限
  3. 您的网站必须公开可用
  4. 您的网站必须已准备好生产环境。

由于这些条件的限制, DocSearch 只适合用在开源的技术文档或技术博客中,所以从 DevNow 开源博客项目的定位来说,还是比较适适合的。为什么突然想着要优化一下搜索组件呢?

今天心血来潮想在 blog 上找一篇文章,用搜素的功能发现搜不出来😂,搜索挂了?然后突然想起来之前由于想着在 blog 中可能加一些私有的配置或者尝鲜的功能,所有 fork 了一份变成 私有项目了,这样就不符合 DocSearch 的 网站必须是公开的这个限制了。

其实用下来我个人感觉还有以下几点不是很满意的地方:

  1. 配置麻烦,需要在 Algolia 上注册账号,然后创建一个应用,然后在项目里配置一些 api-key 信息。
  2. 搜索信息索引的配置可能需要自己在平台上定制化一些 config ,开始可能会比较迷茫。
  3. 索引可能会不及时,默认一周会重新索引一次,所以刚发布的文章可能无法被搜索到。

所以一怒之下就想着改一下,之前想着看看其他的方案,之前在在 shadcn/ui 中看到了一个 Command + K 的搜索组件,所以就想着能不能在 DevNow 中也实现一下。这个实现的方案是基于 cmdk 这个库来实现的, Nextjs 官网应该也是这个实现方案。

cmdk

集成 shadcn/ui

在这里还是推荐使用 shadcn/ui 来集成,因为它提供了很多的组件,而且还提供了一些 hooks 来帮助我们实现一些功能。想着后续可能还会用到一些组件,所以就直接集成了,不得不说这个UI库的样式真是深得我心啊。

安装的话直接跟着 文档 来就好,提供了一些常见框架的集成:

文档

:::tip[注意]
在安装前要先在 tsconfig.json 中配置好 resolve paths
@/* 这个是必须有的,否则 shadcn/ui 无法初始化成功

{"compilerOptions": {// ..."baseUrl": ".","paths": {"@/*": ["./src/*"] // <--- 这个必须有}// ...}
}

:::

安装 Command

文档在 这里

pnpm dlx shadcn@latest add command

一个简单的例子

const Search: FC<Props> = ({ category }) => {const [open, setOpen] = useState(false);useEffect(() => {const down = (e: KeyboardEvent) => {if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {e.preventDefault();setOpen((open) => !open);}};document.addEventListener('keydown', down);return () => document.removeEventListener('keydown', down);}, []);return (<div className='mr-4 hidden items-center lg:flex'><ButtononClick={() => setOpen((open) => !open)}size='sm'className='h-[32px] bg-muted/50 px-2 py-0 text-sm text-muted-foreground shadow-none hover:bg-accent focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring'>Search<kbd className='pointer-events-none ml-1 inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100'><span className='text-xs'>⌘</span>K</kbd></Button>{config.search && (<CommandDialog open={open} onOpenChange={setOpen}><CommandInput placeholder='Type a command or search...' /><CommandList><CommandEmpty>No results found.</CommandEmpty>{category.map((item, index) => (<Fragment key={index}><CommandGroup heading={item.label}>{item.children.map((child, cIndex) => (<CommandItem// 这里需要注意的是:// 选项点击选中的事件是 onSelect 不是 onClickonSelect={() => {window.open(`${location.origin}/posts/${child.id}`, '_blank');}}key={cIndex}className='cursor-pointer'><span>{child.label}</span></CommandItem>))}</CommandGroup>{index === category.length - 1 && <CommandSeparator />}</Fragment>))}</CommandList></CommandDialog>)}</div>);
};

效果展示:

使用 DocSearch

DocSearch

使用 command 替换后:

command

大家觉得哪个更好呢,我个人觉得新版的会更加简洁一点。

遇到的问题

第一版的实现到这里就结束了,然后上线后发现了问题。发现线上的环境突然变卡了,请求也变多了,一看发现堵了很多请求:

文件请求问题

然后就是📌定位问题,发现原因是: 当我在 Astro 中集成 React 框架时,如果组件是运行要求在客户端运行时:

<Search client:only='react' />

在通过 client:only 来标记的组件中获取所有文件的标题时,会把所有的请求一遍,这里我的理解是在客户端没有这些信息,所有执行的时候会构建一份。

这里如果改下数据源,将数据传递给 Search的话,可以规避掉这个问题。


<Search category={category}  client:only='react'>

原文链接:https://www.laughingzhu.cn/posts/cdmk

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/791870.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

项目协同开发 or 拷贝项目

项目协同开发 or 拷贝项目 给另人项目时一般需要给代码 requiremenets.txtpip freeze > requiremenets.txt #requiremenets.txt 生成方式获得别人代码 pip install -r requiremenets.txt # 自动将:requiremenets.txt 对应的版本进行安装无网络问题-解决安装第三方模块…

深入浅出Stream流

Java 8的新特性之一就是流stream,配合同版本出现的 Lambda ,使得操作集合(Collection)提供了极大的便利。 案例引入 在JAVA中,涉及到对数组、Collection等集合类中的元素进行操作的时候,通常会通过循环的方式进行逐个处理,或者使用Stream的方式进行处理。 假设遇到了这么…

决策树之——ID3算法及示例

0 前言本文主要介绍决策树ID3算法,并举出构建示例帮助理解。 读者需要具备的知识:信息熵、条件熵、信息增益。 本文使用数据集为:游玩数据集 1.1节。1 ID3算法简述 ID3(Iterative Dichotomiser 3)算法是一种经典的决策树学习算法,由Ross Quinlan于1986年提出。该算法的主…

AtCoder ABC 369题解

题解前言 本题解部分思路来源于网络,仅供参考 ! A - 369 题目大意 给定 \(A\) , \(B\) 两个整数,求有多少个整数 \(x\) 使得可以通过某种排列使得 \(A\) ,\(B\) ,\(x\) 为等差数列。解题思路 稍加分析即可得到:如果 \(A = B\) 则结果为 \(1\) 。如果 \(A = B\) 但 \((A …

三路快速排序

// 快速排序 function quickSort(arr) {if (arr.length <= 1) {return arr;}const pivot = arr[0];const left = [];const right = [];for (let i = 1; i < arr.length; i++) {if (arr[i] < pivot) {left.push(arr[i]);} else {right.push(arr[i]);}}return quickSort…

三路排序

// 快速排序 function quickSort(arr) {if (arr.length <= 1) {return arr;}const pivot = arr[0];const left = [];const right = [];for (let i = 1; i < arr.length; i++) {if (arr[i] < pivot) {left.push(arr[i]);} else {right.push(arr[i]);}}return quickSort…

8.30 ~ 9.8

文化课奥赛8.30 返校日。 又回到了原来的班(和化奥一个班),一个班有 69 个人; 然后我坐在最角上 🙃 第二天还要开学考试,还有 60% 的原题,这我拿头靠考啊; 遂摆。 发现了坐最后面的好处:离得远老师看不到。 8.31 开学考试。 考试顺序:语 \(\to\) 物 \(\to\) 数 \(\t…

【Spring Boot】整合MyBatis

**整合MyBatis**前言 Spring Boot和MyBatis都是非常流行的Java框架。Spring Boot简化了Spring应用的开发,而MyBatis则是一个优秀的持久层框架,支持自定义SQL、存储过程以及高级映射。 mybatis官方文档:http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconf…

C#设计模式入门实战教程

什么是设计模式 设计模式是对面向对象设计中反复出现的问题的解决方案。它们提供了被反复使用、多数人知晓的、经过分类编目的代码设计经验总结。 设计模式的作用提高代码的可重用性:通过定义一套标准的解决方案,设计模式使得相同或类似的问题可以在不同的项目中复用相同的代…

ES安装

1.初识elasticsearch Elasticsearch的官方网站如下: https://www.elastic.co/cn/elasticsearch/ 1.1.认识和安装 Elasticsearch是由elastic公司开发的一套搜索引擎技术,它是elastic技术栈中的一部分。完整的技术栈包括:Elasticsearch:用于数据存储、计算和搜索 Logstash/Be…

java-URLDNS 链条审计

java-URLDNS 链条审计 URLDNS 链条,是我们学习 java 反序列化的启蒙链条,通过 java 内置的类函数调用,达到 DNS 外带数据的目的。 首先让我们来看一个小实验 从 dnslog.cn 平台获取一个域名 public class urlDNS {public void URL() throws UnknownHostException {InetAddre…

进程间通信——消息队列(通俗易懂)

消息队列 概念消息队列是消息的链表,存放在内核中并由消息队列标识符标识,消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺陷。消息队列包括 POSIX 消息队列和 System V 消息队列。消息队列是 UNIX 下不同进程之间实现共享资源的一种机制,UN…