vue實現移動端左右菜單雙向聯動效果


 

 

 

 話不多說,上demo

<template>
  <div id="app">
    <header>左右列表雙向聯動</header>
    <div class="content">
      <!-- 左側列表 -->
      <ul class="left_title" ref="left">
        <li
          class="title_item"
          v-for="(item, index) in cateData"
          :key="index"
          :class="currentIndex === index ? 'active' : ''"
          @click="change(index)"
        >
          {{ item.name }}
        </li>
      </ul>

      <!-- 右側內容區域 -->
      <div class="right_content">
        <div class="container" ref="container">
          <div ref="foodsUI" class="foodsUI">
            <div class="list">
              <div class="name">健康蔬菜</div>
              <ul>
                <li>蘋果</li>
                <li>西紅柿</li>
                <li>番茄</li>
              </ul>
            </div>
            <div class="list">
              <div class="name">時令蔬菜</div>
              <ul>
                <li>蘋果</li>
                <li>西紅柿</li>
                <li>番茄</li>
              </ul>
            </div>
            <div class="list">
              <div class="name">撥草</div>
              <ul>
                <li>蘋果</li>
                <li>西紅柿</li>
                <li>番茄</li>
              </ul>
            </div>
            <div class="list">
              <div class="name">1</div>
              <ul>
                <li>蘋果</li>
                <li>西紅柿</li>
                <li>番茄</li>
              </ul>
            </div>
            <div class="list">
              <div class="name">2</div>
              <ul>
                <li>蘋果</li>
                <li>西紅柿</li>
                <li>番茄</li>
              </ul>
            </div>
            <div class="list">
              <div class="name">3</div>
              <ul>
                <li>蘋果</li>
                <li>西紅柿</li>
                <li>番茄</li>
              </ul>
            </div>
            <div class="list">
              <div class="name">4</div>
              <ul>
                <li>蘋果</li>
                <li>西紅柿</li>
                <li>番茄</li>
              </ul>
            </div>
            <div class="list">
              <div class="name">5</div>
              <ul>
                <li>蘋果</li>
                <li>西紅柿</li>
                <li>番茄</li>
              </ul>
            </div>
            <div class="list">
              <div class="name">6</div>
              <ul>
                <li>蘋果</li>
                <li>西紅柿</li>
                <li>番茄</li>
              </ul>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import BScroll from 'better-scroll'
export default {
  data() {
    return {
      scroll: '',
      // 右側滑動的y軸坐標(滑動過程中的實時變化)
      scrollY: 0,
      foodsScroll: '',
      // 所有右側分類li的top組成的數組
      tops: [],
      cateData: [
        {
          name: '健康蔬菜'
        },
        {
          name: '時令蔬菜'
        },
        {
          name: '撥草'
        },
        {
          name: '1'
        },
        {
          name: '2'
        },
        {
          name: '3'
        },
        {
          name: '4'
        },
        {
          name: '5'
        },
        {
          name: '6'
        }
      ]
    }
  },
  methods: {
    // 初始化滾動
    initScroll() {
      const container = this.$refs.container
      this.scroll = new BScroll(container)
      /* eslint-disable no-new */
      new BScroll('.left_title', {
        click: true
      })
      // 監聽右側列表
      this.foodsScroll = new BScroll('.container', {
        // 慣性滑動不會被觸發
        probeType: 2,
        click: true
      })
      // 給右側列表綁定scroll監聽
      this.foodsScroll.on('scroll', ({ x, y }) => {
        // math.abs絕對值
        this.scrollY = Math.abs(y)
        console.log(x, y)
      })
      // 給右側列表綁定滾動結束監聽,滾動結束后改變左側列表背景顏色
      this.foodsScroll.on('scrollEnd', ({ x, y }) => {
        this.scrollY = Math.abs(y)
      })
    },
    // 初始化tops
    _initTops() {
      // 1.初始化tops
      const tops = []
      let top = 0
      tops.push(top)
      // 2.搜集
      // 找到所有分類的li
      const lis = this.$refs.foodsUI.getElementsByClassName('list')
      Array.prototype.slice.call(lis).forEach(li => {
        top += li.clientHeight
        tops.push(top)
      })
      // 3。更新數據
      this.tops = tops
      console.log(this.tops)
    },
    // 點擊左側列表右側滾動到相應位置
    change(index) {
      // 得到目標scrollY
      const y = this.tops[index]
      //   立即更新scrollY
      this.scrollY = y
      //   平滑滑動右側列表
      this.foodsScroll.scrollTo(0, -y, 300)
    }
  },
  computed: {
    // 計算當前分類的下表
    currentIndex() {
      //  得到條件數據
      const { scrollY, tops } = this
      // 根據條件計算產出一個結果
      const index = tops.findIndex((top, index) => {
        return scrollY >= top && scrollY < tops[index + 1]
      })
      // 返會結果
      return index
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.initScroll()
      this._initTops()
    })
  }
}
</script>
<style scoped>
header {
  height: 50px;
  width: 100%;
  background-color: green;
  color: #fff;
  font-size: 18px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.content {
  display: flex;
  }
  .left_title {
    flex: 1;
    margin-right: 5px;
   }
    .title_item {
      height: 35px;
      width: 100%;
      border: 1px solid #ccc;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: 18px;
      border-bottom: none;
      
    }
 .title_item :last-child {
        border-bottom: 1px solid #ccc;
      }
  .right_content {
    flex: 3;
    position: relative;
    
  }
  .name {
      text-align: center;
      padding: 20px;
      font-size: 28px;
    }
    .list li{
        font-size: 20px;
    }
    .container {
      overflow: hidden;
      height: calc(100vh - 50px);
    }
.active {
  background-color: red;
  color: #fff;
}
.list {
  height: 200px;
  border: 1px solid #ccc;
}
.foodsUI {
  padding-bottom: 400px;
}
</style>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM