当前位置:首页 > 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 绑定选择值 在 Vue 中可以通过 v-model 指令实现双向数据绑定,适用于下拉选择框(<select>)。以下是一个基本示例: &…

vue实现xss

vue实现xss

XSS 攻击简介 XSS(跨站脚本攻击)是一种常见的安全漏洞,攻击者通过注入恶意脚本到网页中,当其他用户访问该页面时,脚本会在其浏览器中执行,可能导致数据泄露或会话劫持。 Vue 中的 XSS…

vue实现键盘

vue实现键盘

Vue 实现键盘功能 在Vue中实现键盘功能通常涉及监听键盘事件、处理输入以及渲染虚拟键盘界面。以下是几种常见的实现方式: 监听键盘事件 通过@keydown或@keyup指令监听键盘事件,适用于…

vue实现oauth

vue实现oauth

Vue 实现 OAuth 的步骤 安装必要的依赖 确保项目中安装了 axios 和 vue-router。OAuth 通常需要发送 HTTP 请求和处理路由跳转。 npm install axios…

vue实现frame

vue实现frame

Vue 中实现 iframe 的方法 在 Vue 中可以通过直接使用 <iframe> 标签或动态绑定 src 属性来实现 iframe 功能。 基本用法 <template…

vue 实现单选

vue 实现单选

使用 v-model 绑定单选值 在 Vue 中,可以通过 v-model 绑定单选按钮的值。定义一个响应式数据(如 selectedOption),并将其与单选按钮的 value 属性关联。…