实现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>
相关推荐
熊的猫1 小时前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js
别拿曾经看以后~3 小时前
【el-form】记一例好用的el-input输入框回车调接口和el-button按钮防重点击
javascript·vue.js·elementui
川石课堂软件测试3 小时前
性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台
运维·javascript·深度学习·jmeter·docker·容器·grafana
JerryXZR3 小时前
前端开发中ES6的技术细节二
前端·javascript·es6
problc3 小时前
Flutter中文字体设置指南:打造个性化的应用体验
android·javascript·flutter
Gavin_9153 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼4 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
待磨的钝刨5 小时前
【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看
开发语言·javascript·json
Yaml49 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
前端青山10 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js