网站首页 > 知识剖析 正文
前言:
DevNow 项目中我们使用了 DocSearch 来实现搜索功能,但是由于有以下的限制:
- 您的网站必须是技术文档或技术博客。
- 您必须是网站的所有者,或者至少具有更新其内容的权限
- 您的网站必须公开可用
- 您的网站必须已准备好生产环境。
由于这些条件的限制, DocSearch 只适合用在开源的技术文档或技术博客中,所以从 DevNow 开源博客项目的定位来说,还是比较适适合的。为什么突然想着要优化一下搜索组件呢?
今天心血来潮想在 blog 上找一篇文章,用搜素的功能发现搜不出来,搜索挂了?然后突然想起来之前由于想着在 blog 中可能加一些私有的配置或者尝鲜的功能,所有 fork 了一份变成 私有项目了,这样就不符合 DocSearch 的 网站必须是公开的这个限制了。
其实用下来我个人感觉还有以下几点不是很满意的地方:
- 配置麻烦,需要在 Algolia 上注册账号,然后创建一个应用,然后在项目里配置一些 api-key 信息。
- 搜索信息索引的配置可能需要自己在平台上定制化一些 config ,开始可能会比较迷茫。
- 索引可能会不及时,默认一周会重新索引一次,所以刚发布的文章可能无法被搜索到。
所以一怒之下就想着改一下,之前想着看看其他的方案,之前在在 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'>
- 上一篇: 你只会用前端数据埋点 SDK 吗?
- 下一篇: window.location常用的对象属性
猜你喜欢
- 2024-11-24 浏览器跨域问题以及常用解决方案
- 2024-11-24 14个前端小知识,我猜你每天都会遇到
- 2024-11-24 跨域问题的4种解决方案
- 2024-11-24 什么是跨域?跨域解决方法
- 2024-11-24 构建rancher自定义ui的前端镜像
- 2024-11-24 你应该知道的前端小知识,初学者,确定不点进来看看吗?
- 2024-11-24 15个前端小知识
- 2024-11-24 记一场纯JS赛——DiceCTF2021 Web题解
- 2024-11-24 如何基于 Elasticsearch 实现排序沉底或前置
- 2024-11-24 如何查找网站源IP地址
- 04-29php开发者composer使用看这一篇就够了
- 04-29引用和变量声明在不同语言中的实作
- 04-29PHP 没你想的那么差
- 04-29Ubuntu linux 上的 Nginx 和 Php 安装
- 04-29CentOS下通过yum搭建lnmp(单版本PHP)
- 04-29为什么 PHP8 是个高性能版本
- 04-29PHP8函数包含文件-PHP8知识详解
- 04-29使用无参数函数进行命令执行
- 最近发表
- 标签列表
-
- xml (46)
- css animation (57)
- array_slice (60)
- htmlspecialchars (54)
- position: absolute (54)
- datediff函数 (47)
- array_pop (49)
- jsmap (52)
- toggleclass (43)
- console.time (63)
- .sql (41)
- ahref (40)
- js json.parse (59)
- html复选框 (60)
- css 透明 (44)
- css 颜色 (47)
- php replace (41)
- css nth-child (48)
- min-height (40)
- xml schema (44)
- css 最后一个元素 (46)
- location.origin (44)
- table border (49)
- html tr (40)
- video controls (49)