vue3 + Element-plus 开发后台管理系统(26)

103 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第26天,点击查看活动详情

后台项目前端综合解决方案之通用功能开发

headerSearch 原理及方案分析

所谓的 headerSearch 是指页面搜索

原理

headerSearch 是复杂后台系统中一个非常常见的功能,他的目的是使用户方便在搜索框中对当前应用中的所有页面进行检索,以 select 的形式展示出被检索的页面,以达到快速进入的目的

明确了 headerSearch 的作用之后,我们来看一下对应的实现原理

根据前边所说的,headerSearch 可以分为三个核心功能:

1、根据指定的内容多所有的页面进行检索

2、以 select 形式展示检索出的页面

3、通过检索页面可快速进入对应的页面

那么围绕着这三个核心的功能点,我们想要分析它的原理就非常简单了,根据指定内容检索所有页面,把检索出的页面以 select 展示,点击对应的 option 进入

方案

1、创建 headerSearch 组件,用作样式展示和获取用户输入内容

2、获取所有的页面数据,用作被检索的数据源

3、根据用户输入的内容在数据源中进行模糊搜索

4、把搜索到的内容以 select 进行展示

5、监听 selectchange 事件,完成对应跳转

创建 headerSearch 组件

创建 components/headerSearch/index 组件

<template>
  <div :class="{ show: isShow }" class="header-search">
    <svg-icon
      class-name="search-icon"
      icon="search"
      @click.stop="onShowClick"
    />
    <el-select
      ref="headerSearchSelectRef"
      class="header-search-select"
      v-model="search"
      filterable
      default-first-option
      remote
      placeholder="Search"
      :remote-method="querySearch"
      @change="onSelectChange"
    >
      <el-option
        v-for="option in 5"
        :key="option"
        :label="option"
        :value="option"
      ></el-option>
    </el-select>
  </div>
</template>

<script setup>
import { ref } from 'vue'

// 控制 search 显示
const isShow = ref(false)
// el-select 实例
const headerSearchSelectRef = ref(null)
const onShowClick = () => {
  isShow.value = !isShow.value
  headerSearchSelectRef.value.focus()
}

// search 相关
const search = ref('')
// 搜索方法
const querySearch = () => {
  console.log('querySearch')
}
// 选中回调
const onSelectChange = () => {
  console.log('onSelectChange')
}
</script>

<style lang="scss" scoped>
.header-search {
  font-size: 0 !important;
  .search-icon {
    cursor: pointer;
    font-size: 18px;
    vertical-align: middle;
  }
  .header-search-select {
    font-size: 18px;
    transition: width 0.2s;
    width: 0;
    overflow: hidden;
    background: transparent;
    border-radius: 0;
    display: inline-block;
    vertical-align: middle;

    ::v-deep .el-input__inner {
      border-radius: 0;
      border: 0;
      padding-left: 0;
      padding-right: 0;
      box-shadow: none !important;
      border-bottom: 1px solid #d9d9d9;
      vertical-align: middle;
    }
  }
  &.show {
    .header-search-select {
      width: 210px;
      margin-left: 10px;
    }
  }
}
</style>

navbar 中导入该组件

<header-search class="right-menu-item hover-effect"></header-search>
import HeaderSearch from '@/components/HeaderSearch'

有了 headerSearch 之后,接下来就可以处理对应的数据检索了

所谓的数据源指的就是有哪些页面希望搜索

那么对于我们当前的业务而言,我们希望被检索的页面其实就是最哦遍菜单中的页面,那么我们检索的数据源即为左侧菜单对应的数据源

由此,我们可以得到如下代码

<script setup>
import { ref, computed } from 'vue'
import { filterRouters, generateMenus } from '@/utils/route'
import { useRouter } from 'vue-router'
// 检索数据源
const router = useRouter()
const searchPool = computed(() => {
  const filterRoutes = filterRouters(router.getRoutes())
  console.log(generateMenus(filterRoutes))
  return generateMenus(filterRoutes)
})
</script>

对检索数据源进行模糊搜索

如果我们想要进行模糊搜索,那么需要依赖一个第三方库 fuse.js

安装 fuse.js

npm install --save fuse.js

初始化 fuse.js ,更多初始化配置项可点击这里

import Fuse from 'fuse.js'

/**
 * 搜索库相关
 */
const fuse = new Fuse(list, {
  // 是否按优先级进行排序
  shouldSort: true,
  // 匹配长度超过这个值的才会被认为是匹配的
  minMatchCharLength: 1,
  // 将被搜索的键列表。 这支持嵌套路径、加权搜索、在字符串和对象数组中搜索。
  // name:搜索的键
  // weight:对应的权重
  keys: [
    {
      name: 'title',
      weight: 0.7
    },
    {
      name: 'path',
      weight: 0.3
    }
  ]
})

参考对应的 Demo 我们可以得出最终的希望的数据结构如下

[
    {
        "path":"/my",
        "title":[
            "个人中心"
        ]
    },
    {
        "path":"/user",
        "title":[
            "用户"
        ]
    },
    {
        "path":"/user/manage",
        "title":[
            "用户",
            "用户管理"
        ]
    },
    {
        "path":"/user/info",
        "title":[
            "用户",
            "用户信息"
        ]
    },
    {
        "path":"/article",
        "title":[
            "文章"
        ]
    },
    {
        "path":"/article/ranking",
        "title":[
            "文章",
            "文章排名"
        ]
    },
    {
        "path":"/article/create",
        "title":[
            "文章",
            "创建文章"
        ]
    }
]