当前位置:首页 > VUE

vue实现左右联动

2026-02-18 07:24:31VUE

实现左右联动的基本思路

在Vue中实现左右联动效果,通常需要两个列表或区域,通过监听滚动事件或点击事件来同步它们的位置。常见的应用场景包括商品分类与商品列表联动、城市选择器等。

监听滚动事件实现联动

创建两个独立的滚动区域,通过计算滚动位置来同步它们的状态。

vue实现左右联动

<template>
  <div class="container">
    <div class="left" ref="left" @scroll="handleLeftScroll">
      <!-- 左侧内容 -->
    </div>
    <div class="right" ref="right" @scroll="handleRightScroll">
      <!-- 右侧内容 -->
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isScrolling: false
    }
  },
  methods: {
    handleLeftScroll() {
      if (this.isScrolling) return
      this.isScrolling = true
      // 计算并同步右侧滚动位置
      this.$nextTick(() => {
        this.isScrolling = false
      })
    },
    handleRightScroll() {
      if (this.isScrolling) return
      this.isScrolling = true
      // 计算并同步左侧滚动位置
      this.$nextTick(() => {
        this.isScrolling = false
      })
    }
  }
}
</script>

<style>
.container {
  display: flex;
  height: 100vh;
}
.left {
  width: 30%;
  overflow-y: auto;
}
.right {
  width: 70%;
  overflow-y: auto;
}
</style>

使用Intersection Observer API

对于更精确的联动效果,可以使用Intersection Observer API来检测元素是否进入视口。

methods: {
  initObserver() {
    const options = {
      root: null,
      rootMargin: '0px',
      threshold: 0.5
    }

    this.observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          // 联动逻辑
        }
      })
    }, options)

    // 观察所有需要联动的元素
    document.querySelectorAll('.target').forEach(el => {
      this.observer.observe(el)
    })
  }
},
mounted() {
  this.initObserver()
},
beforeDestroy() {
  this.observer.disconnect()
}

基于锚点的联动实现

对于点击跳转类型的联动,可以使用锚点定位方式。

vue实现左右联动

<template>
  <div class="container">
    <div class="left">
      <ul>
        <li v-for="item in items" :key="item.id" @click="scrollTo(item.id)">
          {{ item.name }}
        </li>
      </ul>
    </div>
    <div class="right">
      <div v-for="item in items" :key="item.id" :id="item.id">
        {{ item.content }}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  methods: {
    scrollTo(id) {
      const element = document.getElementById(id)
      if (element) {
        element.scrollIntoView({ behavior: 'smooth' })
      }
    }
  }
}
</script>

性能优化建议

对于大量数据的联动场景,建议使用虚拟滚动技术来提高性能。可以使用第三方库如vue-virtual-scroller来实现。

import { RecycleScroller } from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'

export default {
  components: {
    RecycleScroller
  }
}

完整示例代码

以下是一个商品分类联动的完整示例:

<template>
  <div class="container">
    <div class="left-menu">
      <ul>
        <li 
          v-for="(category, index) in categories" 
          :key="category.id"
          :class="{ active: currentIndex === index }"
          @click="selectCategory(index)"
        >
          {{ category.name }}
        </li>
      </ul>
    </div>

    <div class="right-content" ref="rightContent">
      <div 
        v-for="category in categories" 
        :key="category.id" 
        :ref="'category-' + category.id"
        class="category-section"
      >
        <h3>{{ category.name }}</h3>
        <!-- 商品列表内容 -->
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      currentIndex: 0,
      categories: [
        { id: 1, name: '分类1' },
        { id: 2, name: '分类2' },
        // 更多分类...
      ],
      observer: null
    }
  },
  methods: {
    selectCategory(index) {
      this.currentIndex = index
      const refName = 'category-' + this.categories[index].id
      this.$refs[refName][0].scrollIntoView({ behavior: 'smooth' })
    },
    initIntersectionObserver() {
      const options = {
        root: this.$refs.rightContent,
        threshold: 0.5
      }

      this.observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            const id = entry.target.getAttribute('data-id')
            this.currentIndex = this.categories.findIndex(c => c.id == id)
          }
        })
      }, options)

      this.categories.forEach(category => {
        const element = this.$refs[`category-${category.id}`][0]
        element.setAttribute('data-id', category.id)
        this.observer.observe(element)
      })
    }
  },
  mounted() {
    this.initIntersectionObserver()
  },
  beforeDestroy() {
    if (this.observer) {
      this.observer.disconnect()
    }
  }
}
</script>

<style>
.container {
  display: flex;
  height: 100vh;
}
.left-menu {
  width: 30%;
  overflow-y: auto;
}
.right-content {
  width: 70%;
  overflow-y: auto;
}
.active {
  color: red;
  font-weight: bold;
}
.category-section {
  min-height: 500px;
}
</style>

以上方法可以根据实际需求选择或组合使用,实现不同复杂度的左右联动效果。

标签: vue
分享给朋友:

相关文章

vue多选实现

vue多选实现

Vue 多选实现方法 基础实现(v-model + multiple) 在 Vue 中实现多选可以通过 <select> 元素的 multiple 属性结合 v-model 完成。v-mo…

vue实现录音

vue实现录音

Vue 实现录音功能 在 Vue 中实现录音功能可以通过浏览器提供的 MediaRecorder API 完成。以下是具体实现方法: 引入依赖 确保项目支持现代浏览器 API,无需额外安装库。若需兼…

vue实现treetable

vue实现treetable

Vue实现TreeTable的方法 使用第三方组件库(如Element UI) Element UI的el-table组件支持树形表格展示,通过设置row-key和tree-props属性即可实现。…

实现vue message

实现vue message

实现 Vue 消息提示组件 创建 Message 组件 在 src/components 目录下创建 Message.vue 文件,内容如下: <template> <tran…

vue实现加载

vue实现加载

Vue 实现加载功能的方法 使用 v-if 或 v-show 控制加载状态 通过数据绑定控制加载动画的显示与隐藏。v-if 会完全移除 DOM 元素,v-show 只是切换 display 属性。…

vue实现回顶部

vue实现回顶部

实现方法一:使用 window.scrollTo 在Vue组件中,可以通过调用 window.scrollTo 方法平滑滚动到页面顶部。该方法接受一个配置对象,指定滚动行为为平滑(smooth)。…