从零开始Vue3+Element Plus后台管理系统(十一)——Ctrl+K全局搜索站点路由功能

又是一个有意思的功能——Ctrl+K唤起全局搜索,Vuejs官网、Tailwind CSS官网… 都用上了。

全局搜索功能可以帮助用户快速获取信息定位,对于改进用户体验感还是很有意义的。当然本项目做的是一个低配版,只对路由进行全局搜索,毕竟更多数据内容的搜索还得依靠后端返回,但是前端实现的思路是一致的。

  1. 唤起搜索对话框,通过点击顶部搜索按钮,或者使用快捷键Ctrl+K/Command+K
  2. 搜索框打开时,Input输入框自动focus
  3. 输入关键字,显示对应搜索结果
  4. 点击结果,跳转到对应页面

实现步骤

唤起搜索对话框

点击搜索图标这个太简单了,就不用写了

那么如何使用快捷键Ctrl+K/Command+K呢?可以自己写一个方法来监听按键,但是遇到按键组合的时候就变得复杂起来,所以这里我偷懒了,搬出强大后援vueuse

vueuse #usemagickeys

vueuse有好几个监听按键输入的事件,其中usemagickeys是可以用于按键组合的。

#usemagickeys https://vueuse.org/core/useMagicKeys/#usemagickeys

用法一看就会,引入之后,定义快捷键组合,然后使用watch监听即可。

import { useMagicKeys } from '@vueuse/core'

const keys = useMagicKeys()
const CtrlK = keys['Ctrl+K']
const CommandK = keys['Cmd+K']

watch(CtrlK, (v) => {
  visible.value = true
})

watch(CommandK, (v) => {
  visible.value = true
})

自动聚焦 focus Input

打开对话框后,当然是希望可以焦点直接落在input输入框上,直接开始输入搜索。
需要使用el-dialog的open事件,对话框打开后,在nextTick中,focus the input element。

  <el-dialog
    v-model="visible"
    append-to-body
    :show-close="false"
    @open="onOpen"
    @close="onClose"
  >
    <template #header="{ close, titleId, titleClass }">
      <el-input
        placeholder="搜索全站"
        v-model="keyword"
        @input="search"
        ref="inputRef"
      />
    </template>
...
function onOpen() {
  nextTick(() => {
    inputRef.value.focus()
  })
}
...

输入关键字,显示对应搜索结果

这里只搜索页面路由,搜索的结果集来自于项目中所有路由。

使用router.options.routes可以得到所有的路由,它是一个树状结构的数据,你可以遍历这棵树进行搜索。但我更喜欢把它扁平化之后再操作。

在对话框打开时,把路由数扁平化,以供搜索时使用。

这里注意把完整路径拼起来保存到扁平后的数组中,我们就可以直接在渲染的搜索结果列表中点击跳转到对应路由了。

function flatJson(jsonData: RouteRecordRaw[], fp?: '') {
  return jsonData.reduce((pre, cur) => {
    const { children = [], ...item } = cur
    let fullPath = fp ? fp + '/' + cur.path : cur.path
    fullPath = fullPath.replace(/\/+/g, '/')

    return pre.concat([{ ...item, fullPath }], flatJson(children, fullPath))
  }, [] as RouteRecordRaw[])
}

搜索判断路由的name和title,模糊匹配关键字。

function search() {
  list.value = flatRouteList.filter(
    (val: RouteRecordRaw) =>
      val?.name?.toLowerCase().indexOf(keyword.value.toLowerCase()) > -1 ||
      val?.meta?.title?.toLowerCase().indexOf(keyword.value.toLowerCase()) > -1
  )
}

跳转页面

搜索结果数据中包含了完整路由数据,所以只需要router.push(xxx),跳转的时候记得要调用关闭对话框的方法,要不然跳到新路由,对话框还在页面上😄

其实这个功能最麻烦的地方就是使用快捷键组合,vueuse完美解决了最棘手的部分,剩下的步骤基本都是基础操作,按步骤完成即可。

因为ts不熟练,所以代码有不少爆红的地方,还是要专门找一天好好学习ts才行啊,项目中红色波浪线〰️越来越多了。

项目地址

本项目GIT地址:github.com/lucidity99/…

如果有帮助,给个star ✨ 点个赞👍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

immocha

人生得意须尽欢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值