首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

搜索组件优化 - Command ⌘K

编程知识
2024年09月03日 20:48

前言:

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'>
      <Button
        onClick={() => 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 不是 onClick
                      onSelect={() => {
                        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

From:https://www.cnblogs.com/LaughingZhu/p/18395521
本文地址: http://www.shuzixingkong.net/article/1709
0评论
提交 加载更多评论
其他文章 C#自定义控件—文本显示、文本设值
C#用户控件之文本显示、设定组件 如何绘制一个便捷的文本显示组件、文本设值组件(TextShow,TextSet)? 绘制此控件的目的就是方便一键搞定标签显示(可自定义方法显示文本颜色等),方便自定义方法又省略了挨个拖拽的过程 纯定义属性 【文本设定】:字体、标签、值、单位;事件方法:Enter、L
C#自定义控件—文本显示、文本设值
CMake构建学习笔记14-依赖库管理工具
如果说做C/C++开发最大的痛点是什么,那么一定是缺少一个官方的统一的包管理器。认真的说,如果你要用C/C++干点什么,至少需要(Windows系统下): C/C++语言本身、标准库、以及操作系统API几乎干不了什么,除非你真的想从零开始造轮子。 开始找一些现成的实现组成依赖库。最好看能不能找到预编
使用.NET源生成器(SG)生成项目的版本号信息
之前写过一篇 源生成器生成自动注入的代码 主要是通过SyntaxProvider查找标注特性实现 其实除了SyntaxProvider之外还有几个很重要的Provider,比如:MetadataReferencesProvider,AdditionalTextsProvider,AnalyzerCo
使用.NET源生成器(SG)生成项目的版本号信息
Python批量分割Excel后逐行做差、合并文件的方法
本文介绍基于Python语言,针对一个文件夹下大量的Excel表格文件,基于其中每一个文件,首先依据某一列数据的特征截取我们需要的数据,随后对截取出来的数据逐行求差,并基于其他多个文件夹中同样大量的Excel表格文件,进行数据跨文件合并的具体方法~
Python批量分割Excel后逐行做差、合并文件的方法 Python批量分割Excel后逐行做差、合并文件的方法 Python批量分割Excel后逐行做差、合并文件的方法
英语疑问句倒装特征以及从句的正常语序
上一篇介绍了英文中的五大基本句型,在进一步介绍句子如何在五大句型之上如何各种添枝加叶变得复杂之前,我们先来搞懂英语疑问句倒装特征以及从句的正常语序。 这是至关重要的一件事,但其实太多初学者都给忽略了,在懵圈中苦学了很久,结果在实际应用时产生了各种混乱,事倍而功半。 本文想通过举例的方式,来试图讲清这
英语疑问句倒装特征以及从句的正常语序
多线程、任务、异步的区别
Task和Thread的区别 这是一个高频,深刻的问题,无论去哪都逃不过被询问这个问题。Task是基于Thread的,这是众所周知的。但是Task和Thread的联系如此简单和纯粹确实我没想到的。甚至只需要几十行代码就能呈现其原理。一个简单的模拟实例说明Task及其调度问题,这真是一篇好文章。 任务
多线程、任务、异步的区别 多线程、任务、异步的区别
论文速读纪录 - 202408
特别鸣谢kimi,以下论文均在kimi辅助下阅读。 目录 RMIB: Representation Matching Information Bottleneck for Matching Text Representations AttentionRank: Unsupervised keyphr
论文速读纪录 - 202408 论文速读纪录 - 202408 论文速读纪录 - 202408
【题目全解】ACGO挑战赛#8
前言:本次挑战赛的难度相较于前面几期有所提升,主要还是因为集训的关系,出题组的成员们没有充裕的时间想原创题目(so,只能原模原样搬运某一场 ABC 的考试了。)Anyway,AK 了就行。 备注:由于 Python 的常数过大,本题解暂不同步更新 Python 版本的题解。 第一题 - Inters