vue实现字母导航

本文介绍了如何在Vue.js项目中创建字母导航功能,通过组件化的方式实现对数据的筛选和展示,帮助用户快速找到目标内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<template>
  <div class="Index">
    <div class="in_box">
      <div class="pl_pr">
        <!-- 顶部文本 -->
        <p class="top_p">
          请选择你所在学校,就可以看到该学校信息服务群二维码啦~
        </p>
        <!-- 搜索框 -->
        <div class="search_box">
          <input
            v-model="keyWord"
            class="inp"
            type="text"
            placeholder="搜索学校"
          />
          <img
            @click="getList"
            class="search_img"
            src="@/assets/images/select_right.png"
            alt=""
          />
        </div>
      </div>
      <!-- 学校列表 -->
      <div class="country_border" ref="countryList">
        <div v-for="(item, index) in dataList" :key="index">
          <div class="initials" :data-en="item.title">{{ item.title }}</div>
          <div
            class="item_data"
            :class="{ active: schoolId == item1.collegeId }"
            v-for="(item1, index1) in item.collegeData"
            :key="index1"
            @click="schoolId = item1.collegeId"
          >
            <div>{{ item1.name }}</div>
          </div>
        </div>
        <div class="char_list_border">
          <ul
            class="char_list"
            ref="charBar"
            @touchstart="e => touchStart(e)"
            @touchmove="e => touchMove(e)"
            @touchend="e => touchEnd(e)"
          >
            <li
              class="char_item"
              v-for="(char, index) in charList"
              :key="index"
            >
              {{ char }}
            </li>
          </ul>
        </div>
        <div class="char_tip" v-show="isTouching">{{ lastChar }}</div>
      </div>

      <!-- 确认按钮 -->
      <div class="sure_btn" @click="getEwm">确认</div>
    </div>
  </div>
</template>

<script>
import { collegeList } from "@/http/Api.js";
export default {
  data() {
    return {
      // 选中学校的id
      schoolId: "",
      // 数据列表
      dataList: [],
      // 搜索框关键字
      keyWord: "",
      isTouching: false,
      boxClientTop: 150,
      lastChar: "A",
      charList: "",
      // 选中的学校的名字
      selectName: ""
    };
  },
  computed: {},
  created() {
    this.getList();
  },
  methods: {
    // 跳转到二维码页面
    getEwm() {
      if (!this.schoolId) {
        alert("请选择学校");
      } else {
        this.$router.push("/Ewm?id=" + this.schoolId);
      }
    },
    // 获取数据列表
    async getList() {
      const { status, result } = await collegeList({
        keyWord: this.keyWord
      });

      if (status == 100) {
        this.dataList = result.collegeMappings;
        this.charList = result.rightList;
      }
    },
    touchStart(e) {
      e.preventDefault();
      this.isTouching = true;
      const char = this.getChar(e.touches[0].clientY);
      this.gotoChar(char);
    },
    touchMove(e) {
      e.preventDefault();
      const char = this.getChar(e.touches[0].clientY);
      this.gotoChar(char);
    },
    touchEnd(e) {
      e.preventDefault();
      this.isTouching = false;
    },
    getChar(clientY) {
      const charHeight = this.$refs.charBar.offsetHeight / this.charList.length;
      const index = Math.floor((clientY - this.boxClientTop) / charHeight);
      return this.charList[index];
    },
    gotoChar(char) {
      if (char === this.lastChar) {
        return false;
      }
      this.lastChar = char;
      if (char === "*") {
        this.$refs.countryList.scrollTop = 0;
      } else if (char === "#") {
        this.$refs.countryList.scrollTop = this.$refs.countryList.scrollHeight;
      }
      const target = document.querySelector('[data-en="' + char + '"]');
      if (target) {
        target.scrollIntoView();
      }
    }
  }
};
</script>

<style lang="scss" scpoed>
.Index {
  width: 100vw;
  height: 100vh;
  background-image: url("../assets/images/beijing.png");
  background-size: 100% 100%;
  padding: 0.3rem;
  box-sizing: border-box;
  font-size: 0.26rem;
  color: #333;
  .in_box {
    width: 100%;
    height: 100%;
    background-color: #fff;
    border-radius: 0.16rem;
    box-sizing: border-box;
    .pl_pr {
      padding: 0.4rem 0.3rem 0.2rem 0.3rem;
    }
    .top_p {
      font-size: 0.28rem;
      line-height: 0.42rem;
      margin-bottom: 10px;
    }
  }
  .search_box {
    width: 100%;
    background-color: pink;
    position: relative;
    .inp {
      width: 100%;
      line-height: 0.6rem;
      height: 0.6rem;
      border: 0.01rem solid #e2e2e2;
      padding: 0 0.2rem;
      outline: none;
      box-sizing: border-box;
      font-size: 0.26rem;
    }
    .search_img {
      position: absolute;
      width: 0.3rem;
      height: 0.3rem;
      right: 0.2rem;
      top: 50%;
      transform: translateY(-50%);
    }
  }
  .country_border {
    flex: 1;
    overflow: auto;
    position: relative;
    height: calc(100vh - 4.3rem);
    font-size: 0.26rem;
    .initials {
      padding: 0 0.5rem;
      background-color: #efefef;
      line-height: 0.4rem;
      color: #fe5722;
    }
    .item_data {
      line-height: 0.6rem;
      padding: 0 0.5rem;
      &.active {
        background-color: rgba(254, 87, 34, 0.1);
        color: #fe5722;
      }
    }
  }
  .char_list_border {
    position: fixed;
    right: 0.8rem;
    top: 2.5rem;
    width: 20px;
    height: calc(100vh - 4.3rem);
    margin: 0;
    box-sizing: border-box;
  }
  .char_list {
    list-style-type: none;
    padding-left: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    height: 100%;
    box-sizing: border-box;
  }
  .char_item {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
  }
  .char_tip {
    position: fixed;
    width: 50px;
    height: 50px;
    top: 0;
    right: 0;
    left: 0;
    bottom: 0;
    margin: auto;
    background-color: gray;
    border-radius: 6px;
    color: #fff;
    font-size: 24px;
    font-weight: 700;
    line-height: 50px;
    text-align: center;
  }
  .sure_btn {
    width: 5rem;
    background-color: #fe5722;
    line-height: 0.72rem;
    text-align: center;
    font-size: 0.32rem;
    font-weight: bold;
    color: #fff;
    margin: 0.4rem auto;
    border-radius: 0.36rem;
  }
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值