实现A-Z滑动检索菜单

写个这小玩意真麻烦

html 复制代码
<template>
  <div id="retrieve-components">
    <el-input v-model="searchVal" @input="search" placeholder="请输入" class="mb-10"></el-input>
    <div class="box flex" id="box">
      <div class="letter">
        <div v-for="(item, index) in letter" :key="index" class="mb-2 item" :class="[{active:selectItem == item}]" :id="`left-key-${item}`" @click="retrieveClick(item)">
          {{ item }}
        </div>
      </div>

      <div class="data-right-box" ref="scrollContainer" @scroll="handleScroll">
        <div v-for="(item, index) in peoArray" :key="index" @click="onSelect(item, index)">
          <p class="data-key" :id="`right-key-${item.key}`">{{ item.key }}</p>
          <p class="data-list" v-for="(ele, e) in item.list" :key="e">{{ ele.name }}</p>
        </div>
      </div>

    </div>
    <el-tree :data="peoArray" :props="defaultProps" show-checkbox node-key="id" default-expand-all :expand-on-click-node="false">
      <span class="custom-tree-node" slot-scope="{ node, data }">{{ node.label }}</span>
    </el-tree>
  </div>
</template>

<script>
export default {
  data() {
    return {
      selectItem: "A",
      letter: [],
      defaultProps: {
        children: 'list',
        label: 'name'
      },
      peoArray: [
        {key: "A", list: [{name: "安吉"}, {name: "安吉"}]},
        {key: "B", list: [{name: "bar饿啊额日"}, {name: "芭比"}]},
        {key: "C", list: [{name: "啛啛喳喳"}, {name: "吃炒菜"}]},
        {key: "D", list: [{name: "滴滴滴"}]},
        {key: "E", list: [{name: "鹅鹅鹅"}]},
        {key: "F", list: [{name: "方慧"}]},
        {key: "G", list: [{name: "哥哥"}]},
        {key: "H", list: [{name: "话说"}]},
        {key: "I", list: [{name: "ID额我热饭v"}]},
        {key: "J", list: [{name: "接化发"}]},
        {key: "K", list: [{name: "KFC"}]},
        {key: "L", list: [{name: "吕布"}]},
        {key: "M", list: [{name: "没读书"}]},
        {key: "N", list: [{name: "牛头人"}]},
        {key: "O", list: [{name: "O泡果奶"}]},
        {key: "P", list: [{name: "判断得我"}]},
        {key: "Q", list: [{name: "秦三儿"}]},
        {key: "R", list: [{name: "如果更方便"}]},
        {key: "S", list: [{name: "塞班"}]},
        {key: "T", list: [{name: "糖糖"}]},
        {key: "U", list: [{name: "U哈哈哈哈"}]},
        {key: "V", list: [{name: "V ME 50"}]},
        {key: "W", list: [{name: "王富贵"}]},
        {key: "X", list: [{name: "喜羊羊"}]},
        {key: "Y", list: [{name: "阳顶天"}]},
        {key: "Z", list: [{name: "自发热"}]}
      ],
      leftClickFlag: false,
      searchVal: "",
    };
  },
  computed: {},
  mounted() {
    this.letter = Array.from({length: 26}, (_, i) => String.fromCharCode(65 + i));
    // this.$refs.scrollContainer.addEventListener('scroll', this.debounce(this.handleScroll, 200));
  },
  methods: {
    search() {

    },
    handleScroll(event) {
      let timeout;
      if (timeout) {
        clearTimeout(timeout);
        timeout = null;
      }
      timeout = setTimeout(() => {
        // this.leftClickFlag = false;
        const container = document.querySelector('#box');
        const closestElement = this.getClosestElementToTop(container);
        this.selectItem = closestElement;
        // if (!this.leftClickFlag) {
        this.scrollOn(`left-key-${closestElement}`);
        // }
      }, 500);
    },
    debounce(func, wait) {
      let timeout;
      return function (...args) {
        const later = () => {
          clearTimeout(timeout);
          func.apply(this, args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
      };
    },
    getClosestElementToTop(container) {
      const elements = document.querySelectorAll(".data-key");
      // console.log("container.getBoundingClientRect().top", container.getBoundingClientRect().top);
      let closestElement = null;
      let closestDistance = Infinity;
      for (let element of elements) {
        const rect = element.getBoundingClientRect();
        const distance = Math.abs(rect.top - container.getBoundingClientRect().top);
        // console.log("rect.top", rect.top, distance, distance < closestDistance);
        if (distance < closestDistance) {
          closestDistance = distance;
          closestElement = element;
        }
      }
      return closestElement.innerText;
    },
    retrieveClick(item) {
      this.leftClickFlag = true;
      this.selectItem = item;
      this.scrollOn(`right-key-${item}`);
    },
    scrollOn(item) {
      let target = document.getElementById(item);
      if (target) {
        target.scrollIntoView({behavior: "smooth" /*smooth || auto*/});
      }
    },
    // 点击通讯录
    onSelect(item, index) {
      console.log(item, index);
    }
  },
  beforeDestroy() {
    // this.$refs.scrollContainer.removeEventListener('scroll', this.debounce(this.handleScroll, 200));
  }
};
</script>

<style lang="scss" scoped>
#retrieve-components {
  padding: 10px;
  width: 400px;
  height: 200px;
  background: #fff;

  .box {
    height: calc(100% - 42px);

    .letter {
      font-size: 12px;
      margin-right: 20px;
      justify-content: space-between;
      overflow-y: auto;

      .item {
        padding: 1px;
        cursor: pointer;
        text-align: center;

        &.active {
          background: pink;
        }
      }
    }

    .data-right-box {
      height: 100%;
      overflow-y: auto;
      flex: 1;
      width: 100%;
      padding: 0 10px;

      .data-key {
        margin: 10px 0;
        font-size: 12px;
        background-color: #f3efef;
      }

      .data-list {
        margin: 20px 0;
      }
    }
  }
}

</style>
相关推荐
OEC小胖胖7 小时前
告别 undefined is not a function:TypeScript 前端开发优势与实践指南
前端·javascript·typescript·web
行云&流水7 小时前
Vue3 Lifecycle Hooks
前端·javascript·vue.js
老虎06278 小时前
JavaWeb(苍穹外卖)--学习笔记04(前端:HTML,CSS,JavaScript)
前端·javascript·css·笔记·学习·html
三水气象台8 小时前
用户中心Vue3网页开发(1.0版)
javascript·css·vue.js·typescript·前端框架·html·anti-design-vue
烛阴8 小时前
Babel 完全上手指南:从零开始解锁现代 JavaScript 开发的超能力!
前端·javascript
CN-Dust9 小时前
[FMZ][JS]第一个回测程序--让时间轴跑起来
javascript
全宝10 小时前
🎨前端实现文字渐变的三种方式
前端·javascript·css
yanlele10 小时前
前端面试第 75 期 - 2025.07.06 更新前端面试问题总结(12道题)
前端·javascript·面试
妮妮喔妮11 小时前
【无标题】
开发语言·前端·javascript
fie888911 小时前
浅谈几种js设计模式
开发语言·javascript·设计模式