You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue2动态类绑定失效:导航栏无法高亮当前所在区块

Vue2导航高亮:Intersection Observer无法更新data的修复方案

问题根源

你遇到的核心问题是Intersection Observer回调函数的this指向错误:使用普通function定义回调时,this指向的是Observer实例本身,而非Vue组件实例。所以你修改的this.activeEntry并不是Vue data里的变量,控制台打印的只是Observer对象上新增的属性,自然无法触发视图更新。

修复方法(两种可选)

方法1:改用箭头函数定义回调

箭头函数会继承外部作用域的this(也就是Vue组件实例),直接修改data变量:

mounted() {
  this.observer = new IntersectionObserver(
    (entries) => { // 替换为箭头函数
      const active = entries.filter((e) => e.isIntersecting);
      if (active.length) {
        this.activeEntry = active[0].target.childNodes[0].id;
        console.log(this.activeEntry); // 现在指向Vue的data变量
      }
    },
    { threshold: [0.5] }
  );
  // 监听逻辑简化为forEach遍历
  const matches = document.querySelectorAll("section.box");
  matches.forEach(item => this.observer.observe(item));
}

方法2:提前保存Vue实例的引用

如果习惯用普通函数,可以在回调外把Vue实例存起来:

mounted() {
  const vm = this; // 保存Vue实例引用
  this.observer = new IntersectionObserver(
    function(entries) {
      const active = entries.filter((e) => e.isIntersecting);
      if (active.length) {
        vm.activeEntry = active[0].target.childNodes[0].id; // 用vm访问data
        console.log(vm.activeEntry);
      }
    },
    { threshold: [0.5] }
  );
  const matches = document.querySelectorAll("section.box");
  matches.forEach(item => this.observer.observe(item));
}

额外优化建议

  1. 避免依赖childNodes[0]:childNodes[0]容易受DOM结构变化影响,建议直接给监听的section设置data-id属性:
    <section class="box" data-id="Entry-c">...</section>
    
    然后在回调里取标识:
    this.activeEntry = active[0].target.dataset.id;
    
  2. 清理Observer避免内存泄漏:在组件销毁时停止监听:
    beforeDestroy() {
      if (this.observer) {
        const matches = document.querySelectorAll("section.box");
        matches.forEach(item => this.observer.unobserve(item));
        this.observer.disconnect();
      }
    }
    

修改后的完整代码

<template>
  <div id="Navigation-c">
    <ul>
      <li :class="{ active: activeEntry == 'Entry-c' }" v-scroll-to="'#Entry-c'">
        <font-awesome-icon icon="fa-solid fa-chevron-up" />
      </li>
      <li :class="{ active: activeEntry == 'Motivation-c' }" v-scroll-to="'#Motivation-c'">
        <p>Intro</p>
      </li>
      <li :class="{ active: activeEntry == 'NeuralNetworks-c' }" v-scroll-to="'#NeuralNetworks-c'">
        <p>AI</p>
      </li>
      <li :class="{ active: activeEntry == 'About-c' }" v-scroll-to="'#About-c'">
        <p>About</p>
      </li>
      <li :class="{ active: activeEntry == 'Contact-c' }" v-scroll-to="'#Contact-c'">
        <p>Contact</p>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "Navigation-c",
  data: () => ({
    activeEntry: '',
    observer: null
  }),
  mounted() {
    this.observer = new IntersectionObserver(
      (entries) => {
        const active = entries.filter((e) => e.isIntersecting);
        if (active.length) {
          // 若section已设置data-id,建议改用下面一行
          // this.activeEntry = active[0].target.dataset.id;
          this.activeEntry = active[0].target.childNodes[0].id;
        }
      },
      { threshold: [0.5] }
    );
    const matches = document.querySelectorAll("section.box");
    matches.forEach(item => this.observer.observe(item));
  },
  beforeDestroy() {
    if (this.observer) {
      const matches = document.querySelectorAll("section.box");
      matches.forEach(item => this.observer.unobserve(item));
      this.observer.disconnect();
    }
  }
};
</script>

<style lang="scss" scoped>
.active {
  color: red !important;
}
</style>

内容的提问来源于stack exchange,提问作者Kilian Kramer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 18:55:42