根据首字母列表选择城市


vue实现根据首字母列表点击选择城市


实现点击字母跳转相对应城市,先看下效果
在这里插入图片描述
在这里插入图片描述

先获取城市列表

 async getCityList() {
 		//封装的请求调用
      const res = await intercept({
        method: "general.uppercitylist"//接口参数
      });
      let arr = [];
      if (res.status == true) {
        for (let key in res.data.list) {
          let obj = {
            initial: null,
            list: null
          };
          obj.initial = key;
          obj.list = res.data.list[key];
          arr.push(obj);
        }
        this.listData = arr;
        console.log(this.listData);       
      }
    },

得到的listData格式是这样的

在这里插入图片描述
在这里插入图片描述


对数据处理一波,提取字母列表

async getCityList() {
      const res = await intercept({
        method: "general.uppercitylist"
      });
      let arr = [];
      if (res.status == true) {
        for (let key in res.data.list) {
          let obj = {
            initial: null,
            list: null
          };
          obj.initial = key;
          obj.list = res.data.list[key];
          arr.push(obj);
        }
        this.listData = arr;
        console.log(this.listData);
        // 提取字母列表
        this.quickPanelData.forEach((item, index) => {
          const navItem = item.navName || item.title || "标题";
          this.letterList.push(navItem);
        });
        // 处理城市列表数据
        this.listData.forEach((item, index) => {
          this.letterList.push(item.initial);
        });
        // console.log(this.letterList);
      }
    },

处理过后的数据

在这里插入图片描述

直接奉上全部代码

<template>
  <div class="selectCityMain" ref="DOM">
    <div ref="Box">
      <div v-if="letter.length > 0" class="now-sort">{{letter}}</div>
      <div :class="['now-letter', fadeFlag?'fadeIn':'']">{{letter}}</div>
      <div class="letterBox">
        <p :class="idx === activtIndex?'active':''" v-for="(item,idx) in letterList" :key="idx" @click="scrollSelect(idx)">{{item}}</p>
      </div>
      <div>
        <div class="hostCityBox">
          <div
            class="base-wrap"
            v-for="(item, index) in quickPanelData"
            :classesAttr="item"
            :key="index"
          >
            <div class="title">{{item.title}}</div>
            <div class="panel host" ref="host">
              <span
                class="item"
                v-for="(cy,idx) in item.data"
                :key="idx"
                @click="selectCity(cy)"
              >{{cy}}</span>
            </div>
          </div>
        </div>
        <div class="cityListBox">
          <div class="base-wrap" v-for="(tle,tleIdx) in listData" :key="tleIdx">
            <div class="title">{{tle.initial}}</div>
            <div class="panel">
              <p
                class="cityName"
                v-for="(city,idx1) in tle.list"
                :key="idx1"
                @click="selectCity(city.name)"
              >{{city.name}}</p>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import { intercept } from "../../service/api";
import config from "../../utils/config";

export default {
  data() {
    return {
      cityname: "",
      citycode: "",
      city: "",
      province: "",
      listData: [],
      letterList: [],
      letter: "",
      fadeFlag: false,
      scrolly: 0,
      activtIndex:0,
      quickPanelData: [
        {
          title: "当前城市",
          navName: "当前",
          data: [this.$store.getters.cityname],
        },
        {
          title: "热门城市",
          navName: "热",
          data: [
            "北京市",
            "上海市",
            "广州市",
            "深圳市",
            "成都市",
            "重庆市",
            "杭州市",
            "三亚市",
            "武汉市"
          ],
        }
      ]
    };
  },
  async created() {
    this.getCityList();
  },
  mounted() {
    // 先给页面注册滚动事件
    window.addEventListener("scroll", this.handleScroll, true);
  },
  methods: {
    handleScroll() {
      var scrollTop = document.documentElement.scrollTop;
    },
    // 获取城市列表
    async getCityList() {
      const res = await intercept({
        method: "general.uppercitylist"
      });
      let arr = [];
      if (res.status == true) {
        for (let key in res.data.list) {
          let obj = {
            initial: null,
            list: null
          };
          obj.initial = key;
          obj.list = res.data.list[key];
          arr.push(obj);
        }
        this.listData = arr;
        console.log(this.listData);
        // 提取字母列表
        this.quickPanelData.forEach((item, index) => {
          const navItem = item.navName || item.title || "标题";
          this.letterList.push(navItem);
        });
        // 处理城市列表数据
        this.listData.forEach((item, index) => {
          this.letterList.push(item.initial);
        });
      }
    },
    //计算滚动条滚动的距离
    scrollSelect(index) {
      this.letter = this.letterList[index];
      this.fadeFlag = true;
      this.activtIndex = index;
      this.Timer = setTimeout(() => {
        this.fadeFlag = false;
      }, 1000);
      let scrolly = 0;
      //热门城市自适应高度获取元素的高度
      let hostHeight = document.getElementsByClassName("host")[1].offsetHeight;
      let topHeght = 132 + hostHeight;
      if (index === 0) {
        this.scrolly = 0;
      } else if (index === 1) {
        this.scrolly = 92;
      } else if (index === 2) {
        this.scrolly = topHeght;
      } else if (index >= 3) {
        let len = 0;
        this.listData.forEach((item, idx) => {
          if (idx < index - 2) {
            len += item.list.length;
          }
        });
        this.scrolly = topHeght + (index - 2) * 40.8 + len * 35;
      }
      document.documentElement.scrollTop = this.scrolly;
    },
		//点击选择城市
    selectCity(name) {
      this.cityname= name;
      this.$store.commit("changeCityName", name);
      this.$router.push({ path: "/home" });
    },

    async onSelected(data) {
      //选择城市动态更新到首页
      this.cityname = data.city.value;
      this.$store.commit("changeCityName", this.cityname);
      this.$router.push({ path: "/home" });
    }
  },
  computed: {
    isFollow() {
      return this.$store.getters.cityname; //监听城市名字改变
    }
  },
  watch: {
    async isFollow(newVal, oldVal) {
      const res = await intercept({
        method: "general.getcityid",
        name: this.$store.getters.cityname
      });
      this.citycode = res.data.list.id;
      this.$store.commit("changeCityCode", this.citycode);
    }
  }
};
</script>
<style lang="scss" scoped>
.selectCityMain {
  width: 100%;
  // height: 500px;
  // height: 100%;
  overflow-y: auto;
  position: relative;
  .letterBox {
    width: 35px;
    position: fixed;
    top: 18%;
    right: 0;
    background: rgba(0, 0, 0, 0.5);
    border-radius: 16px;
    padding: 10px 0;
    p {
      font-size: 12px;
      color: #fff;
      text-align: center;
      padding-bottom: 3px;
    }
    .active{
      background: rgba(0, 0, 0, 0.5);
    }
  }
  .now-letter {
    font-size: 60px;
    color: #ccc;
    position: fixed;
    top: 60%;
    left: 50%;
    transform: translate3d(-50%, -50%, 0);
    opacity: 0;

    &.fadeIn {
      animation: fade 1s linear 0ms;
      opacity: 1;
    }
  }
  .now-sort {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    display: flex;
    align-items: center;
    box-sizing: border-box;
    font-size: 14px;
    padding: 10px;
    background: #ccc;
  }
  .hostCityBox {
    width: 100%;
    .base-wrap {
      overflow: hidden;
      .title {
        display: flex;
        align-items: center;
        box-sizing: border-box;
        font-size: 14px;
        padding: 10px;
        background: #ccc;
      }
      .panel {
        display: flex;
        flex-wrap: wrap;
        font-size: 14px;
        padding: 10px;
        padding-right: 30px;
        .item {
          display: flex;
          align-items: center;
          justify-content: center;
          width: 74px;
          border: 1px solid;
          border-radius: 10px;
          margin-bottom: 10px;
          margin-right: 8px;
        }
        &::after {
          display: block;
          content: "";
          width: 200px;
          border: 1px solid transparent;
        }
      }
    }
  }
  .cityListBox {
    width: 100%;
    .title {
      display: flex;
      align-items: center;
      box-sizing: border-box;
      font-size: 14px;
      padding: 10px;
      background: #ccc;
    }
    .panel {
      display: flex;
      flex-wrap: wrap;
      font-size: 14px;
      padding: 0 10px;
      padding-right: 30px;
      .cityName {
        font-size: 14px;
        width: 100%;
        height: 35px;
        display: flex;
        align-items: center;
      }
    }
  }
}
</style>

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值