vue通过better-scroll仿饿了么、美团实现左右联动

在这里插入图片描述
1.

<template>
  <div :style="{height: curHeight + 'px'}" class="visitMaintainContainer">
    <div v-if="isOpen" :style="{height: curHeight + 'px'}">
      <div v-if="right.length>0">
        <section class="box">
          <div class="content" style="height:100%">
            <div ref="left" class="left">
              <ul>
                <li v-for="(item, index) in left" :key="item" ref="menuList" style="font-size: 0.26rem;" :class="{current: index == currentIndex}" @click="item ? selectItem(index) : ''">
                  <div class="SCJ_ellipsisCls_1" :class="{current1: index == currentIndex}">
                    {{ item }}
                  </div>
                </li>
              </ul>
            </div>
            <div ref="right" class="right" style="padding-left: 0.2rem;">
              <ul style="font-size:0.26rem;">
                <li v-for="(item, index) in right" :key="index" class="right-item right-item-hook" style="padding: 0.3rem 0.2rem;margin-top: 0.3rem;" :style="{'height': JSON.stringify(item) !== '{}'? '' : `${curHeight -everyHeight- 99}px`,'background-color': JSON.stringify(item) !== '{}'? '#fff' :''}">
                  <div style="font-size:0.26rem;font-weight:550;margin-bottom:0.3rem" :class="{current2: index == currentIndex}">
                    {{ item.name }}
                    <img v-if="index == currentIndex && index !==everyIndex" src="@/assets/icon_more_red@3x.png" alt="" style="height:0.2rem;vertical-align: middle;">
                  </div>
                  <ul style="display: flex;flex-flow: row wrap;">
                    <li v-for="items in item.children" :key="items.name" style="width: 30%;margin-bottom: 0.2rem;" @click="goMaintainList(items)">
                      <div>
                        <img :src="items.icon" alt="" style="width: 1.3rem;height: 1.3rem;border-radius: 0.08rem;">
                        <div style="margin-top: 0.1rem;font-size:0.22rem">
                          {{ items.name }}
                        </div>
                      </div>
                    </li>
                  </ul>
                </li>
              </ul>
            </div>
          </div>
        </section>
      </div>
      <div v-else :style="{height: curHeight + 'px'}">
        <emptyComponent v-if="!isOpen" content="暂无维修分类" />
      </div>
    </div>
    <div v-else :style="{height: curHeight + 'px'}">
      <emptyComponent content="本城市暂未开通维修服务" />
    </div>
  </div>
</template>

2.

<script>
import { Toast } from 'vant'
import { getVisitMaintainList } from '@/api/visitMaintain/visitMaintain'
import emptyComponent from '@/components/empty'
import BScroll from 'better-scroll'
export default {
  head() {
    return {
      title: '上门维修'
    }
  },
  components: {
    emptyComponent,
  },
  data() {
    return {
      left: [],
      right: [],
      listHeight: [],
      scrollY: 0, //实时获取当前y轴的高度
      clickEvent: false,
      curHeight: 0,
      isOpen: true,
      everyHeight: 0,
      everyIndex: 0,
    }
  },
  computed: {
    currentIndex() {
      const {scrollY,listHeight} = this
      return listHeight.findIndex((tops,index )=>{
        if(index !== this.everyIndex) {
          return  scrollY >= tops && scrollY < listHeight[index + 1]
        }
      })
    },
  },
  mounted() {
    this.curHeight = document.documentElement.clientHeight || document.body.clientHeight
    this.getVisitMaintainList()
  },
  methods: {
    // 跳转维修服务列表页
    goMaintainList(item) {
      this.$router.push({
        path: '/cleanPre/serverProductList',
        query: {
          serviceType: 3, // 上门维修
          title: item.name,
          service_category_id_list: item.id
        }
      })
    },
    // 获取分类列表
    getVisitMaintainList() {
      Toast.loading()
      let regionCode = ''
      if (window.jsMethord && window.jsMethord.getCityCode) {
        regionCode = window.jsMethord.getCityCode()
      } else {
        regionCode = '610100000000'
      }
      getVisitMaintainList(regionCode).then((res) => {
        Toast.clear()
        if (res.data.code === 200) {
          this.isOpen = res.data.data.is_open
          const allData = res.data.data.list
          this.right = allData
          let noRight = [{}]
          this.right = [...this.right,...noRight]
          allData.forEach(element => {
            this.left.push(element.name)
          })
          let noLeft = ['']
          this.left = [...this.left,...noLeft]
          this.$nextTick(() => {
            this._initScroll()
            this._getHeight()
          })
        }
      })
    },
    _initScroll() {
      //better-scroll的实现原理是监听了touchStart,touchend事件,所以阻止了默认的事件(preventDefault)
      //所以在这里做点击的话,需要在初始化的时候传递属性click,派发一个点击事件
      //在pc网页浏览模式下,点击事件是不会阻止的,所以可能会出现2次事件,所以为了避免2次,可以在绑定事件的时候把$event传递过去
      this.lefts = new BScroll(this.$refs.left, {
        click: true
      })
      this.rights = new BScroll(this.$refs.right, {
        click: true,
        probeType: 2  //探针的效果,实时获取滚动高度
      })
      //rights这个对象监听事件,实时获取位置pos.y
      this.rights.on('scroll', (pos) => {
        this.scrollY = Math.abs(Math.round(pos.y))
      })
      this.rights.on('scrollEnd', (pos) => {
        this.scrollY = Math.abs(Math.round(pos.y))
      })
    },
    _getHeight() {
      let rightItems = this.$refs.right.getElementsByClassName('right-item-hook')
      let height = 0
      this.listHeight.push(height)
      for (let i = 0; i < rightItems.length; i++) {
        let item = rightItems[i]
        // 用于解决最后一个自己新增的数据不能点击
        if(i === rightItems.length-2) {
          this.everyHeight = item.clientHeight
          this.everyIndex = i+ 1
        }
        height += item.clientHeight
        this.listHeight.push(height)
      }
    },
    selectItem(index) {
       this.clickEvent = true
      if (!event._constructed) {
        return
      } else {
        let rightItems = this.$refs.right.getElementsByClassName('right-item-hook')
        let el = rightItems[index]
        this.rights.scrollToElement(el, 400)
      }
    }
  },
}
</script>

3.<style scoped> .visitMaintainContainer { background-color: #f6f6f6 } .content { display: flex; position: absolute; /* bottom: 100px; */ width: 100%; overflow: hidden; background: #eee; } .left { flex: 0 0 80px; width: 1.8rem; font-size: 0.3rem; } .left li { width: 100%; height: 100%; display: block; width: 1.8rem; padding: 0.3rem 0; text-align: center; } .current { color: #e72a54; font-weight: 550; background-color: #fff; height: 0.4rem; } .current1 { color: #e72a54; font-weight: 550; background-color: #fff; border-left: 0.08rem solid #e72a54; height: 0.4rem; font-size: 0.3rem; } .current2 { color: #e72a54; } .right { flex: 1; background-color: #f6f6f6; } .right-item { } .right-item li { width: 100%; text-align: center; } </style>

请求到数据格式在这里插入图片描述
注:
1.由于返回的数据格式,需要区分左右双飞翼各一个数组
2.由于数组过少,最后两个滑动定位不到,需在两个数组上各新增一个对象或字符串,用于可以点到最后一个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值