better-scroll插件制作城市选择

下面是完成的效果,点击右侧字母的时候,城市列表跳到对应的城市,页面主要分成三个部分,效果图和代码已经框出来相对应了

city.vue文件(父组件)

父组件主要做的工作就是当点击字母的时候触发letterClick这个事件

将点击的字母赋值给sendClitLetter,然后传递给城市列表组件(子组件 )

子组件的主要工作有(cityList.vue)

 这里主要强调一下如果this.scroll.scrollToElement()没有滚动的话,可以在mounted中实例化对象的时候需要加一个延时器settimeout,我就是这样解决的。

在这里我还遇到一个问题,我看网上实例化一个BScroll对象的时候,有两种写法

第一种

this.scroll = new BScroll(this.$refs.wrapper, {

        click: true,

        scrollY: true

      });

第二种 

this.scroll = new BScroll(this.$refs.wrapper);

我用的是第二种,大无语事件来了,城市什么的都点不了,也就是说 gotoHome()这个方法不生效,我真的想不出为什么(当时死也没想用第一种试试)就一直在各各地方添加点击事件,想看看因为什么,但是无果,然后我就先忙其他事情了,第二天,我改成第一种写法,就可以实现点击了

下面是父组件和子组件全部的代码

父组件(city.vue)

<template>
  <div class="containerOne">
    <!-- 顶部内容 -->
    <div class="Headerwrap">
      <headBar title="城市选择"></headBar>
      <div class="searchWrap">
        <van-search shape="round" background="white" placeholder="请输入城市名或者拼音" />
      </div>
    </div>
    <!-- 字母排序 -->
    <div class="zimuWrap">
      <ul class="list">
        <li
          class="item"
          v-for="item in cityZimuList"
          :key="item"
          :ref="item"
          @click="letterClick"
          @touchstart="touchStart"
          @touchmove="touchMove"
          @touchend="touchEnd"
        >{{item}}</li>
      </ul>
    </div>
    <!-- 城市选择列表 -->
    <city-list @sendList="sendList" :sendCityLetter="sendCityLetter"></city-list>
  </div>
</template>

<script>
import cityList from "../components/List.vue";
import headBar from "@/components/headBar.vue";
export default {
  components: {
    headBar,
    cityList
  },
  
  data() {
    return {
      cityZimu: {}, //城市字母列表--cities
      sendCityLetter: "", //发送给子组件的数据,单个的城市字母
      touchStatus: false, //是否点击字母
      startY: 0
    };
  },

  // 数据更新完毕,且页面完成渲染之后触发的事件
  updata() {
    this.startY = this.$refs["A"][0].offsetTop;
  },
  methods: {
    //发送字母
    sendList(e) {
      this.cityZimu = e;
    },
    //点击字母跳转城市名称首字母
    letterClick(e) {
      this.sendCityLetter = e.target.innerText;
    },
    //点击字母表时的事件
    touchStart() {
      this.touchStatus = true;
    },
    touchMove(e) {
      if (this.touchStatus) {
        const touchY = e.touches[0].clientY - 180; //指针位置到窗口的距离
        //字母下标等于 指针位置 减去 字母距离,最后除以每个字母的高度
        const index = Math.floor((touchY - this.startY) / 20); //字母下标
        if (index >= 0 && this.cityZimuList.length) {
          // this.$emit("changeLetters",this.cityZimuList[index])
          this.sendCityLetter = this.cityZimuList[index];
        }
      }
    },
    touchEnd() {
      this.touchStatus = false;
    }
  },
  computed: {
    cityZimuList() {
      const letters = [];
      for (let i in this.cityZimu) {
        letters.push(i);
      }
      return letters;
    }
  },
  created() {
    this.sendList();
  } 
};
</script>
<style scoped lang="scss">
.containerOne {
  .Headerwrap {
    width: 100%;
    position: fixed;
    position: absolute;
    top: 0;
    left: 0;
    z-index:9999;
    .cityHeader {
      background: #00a5ff;
      // background-color: lightskyblue;
      display: flex;
      height: 10.667vw;

      .icon {
        font-size: 30px;
        display: flex;
        justify-content: center;
        align-items: center;
      }

      .title {
        display: flex;
        justify-content: center;
        align-items: center;
        flex: 1;
        margin-left: -4vw;
      }
    }
  }

  .zimuWrap {
    height: 100%;

    .list {
      //  padding-top: 100px;
      position: fixed;

      top: 26%;
      right: 1.333vw;
      text-align: center;
      flex-direction: column;
      justify-content: center;
      align-items: center;

      .item {
        padding: 0.32vw 0;
      }
    }
  }
}
</style>

子组件(cityList.vue) 

<template>
  <div class="container" ref="wrapper">
    <div class="content">
      <!-- 当前城市 -->
      <div class="adress">
        <div class="title">当前城市</div>
        <div class="button_list">
          <div class="button_wrap">
            <div class="button">{{city}}</div>
          </div>
        </div>
      </div>
      <!-- 热门城市 -->
      <div class="adress">
        <div class="title">热门城市</div>
        <div class="button_list">
          <div class="button_wrap">
            <div
              class="button"
              v-for="item in hotCity"
              :key="item.name"
              @click="gotoHome(item.name)"
            >{{item.name}}</div>
          </div>
        </div>
      </div>
      <!-- 城市选择列表 -->
      <div class="adress" v-for="(item,key) in cityList" :key="key" :ref="key">
        <div class="title">{{key}}</div>
        <div class="list">
          <div
            class="item"
            v-for="item2 in item"
            :key="item2.letter"
            @click="gotoHome(item2.city)"
          >{{item2.city}}</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import BScroll from "better-scroll";
import { getGoodsCityApi, getHotCityApi } from "@/utils/user.js";

export default {
  data() {
    return {
      hotCity: [],
      cityList: {},
      city: "深圳市"
    };
  },
  props: {
    sendCityLetter: {
      type: String,
      default: "A"
    }
  },

  methods: {
    gotoHome(context, city) {
      this.$router.push({ path: "/" });
    }
  },
  created() {
     getHotCityApi().then(res => {
      if (res.data.code == 200) {
        this.hotCity = res.data.data; 
      }
    });
    getGoodsCityApi({}).then(res => {
      if (res.data.code == 200) {
        this.cityList = res.data.data;
        this.$emit("sendList", this.cityList);
      }
    });
  },
  mounted() {
    //setTimeout()解决this.scroll.scrollToElement()无法滚动的问题
    setTimeout(() => {
      this.scroll = new BScroll(this.$refs.wrapper);
    }, 1000);
  },
  computed: {},
  watch: {
    sendCityLetter() {
      if (this.sendCityLetter) {
        let element = this.$refs[this.sendCityLetter][0];
        this.scroll.scrollToElement(element);
      }
    }
  }
};
</script>


<style scoped lang="scss">
.container {
  // padding-top: 25.333vw;
  margin-right: 6.667vw;
  position: absolute;
  top: 94px;
  left: 0;
  bottom: 0;
  right: 0;
  // overflow: hidden;

  .content {
    .adress {
      .title {
        background-color: #f6f5fa;
        // border-bottom: 1px solid #87cefa;
        padding: 2.667vw 0 1.333vw 1.333vw;
      }

      .button_list {
        padding: 1.333vw 2.667vw;
        .button_wrap {
          display: flex;
          width: 100%;
          flex-wrap: wrap;

          .button {
            margin: 1.333vw 0.8vw;
            display: flex;
            width: 30.3%;
            border: 1px solid #dbdbdb;
            border-radius: 16px;
            padding: 0.8vw 0;
            justify-content: center;
            flex-wrap: wrap;
          }
        }
      }

      .list {
        padding-left: 15px;
        .item {
          padding: 1.09vw 0;
          border-bottom: 1px solid #ededed;
        }
      }
    }
  }
}
</style>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值