0

简单用例:特定元素应通过将属性“active”设置为 true (v-bind:class) 来获得活动类。在检查一些条件后,在方法“handleScroll”中,在 foreach 循环中设置属性“active”。

如果我在创建的生命周期中直接调用“handleScroll”,这将有效。

<template>
  <div class="c-sidebar">
    <p
      v-for="(sidebarItem, index) in sidebarItems"
      v-bind:key="index"
      v-bind:class="{ 'active': sidebarItem.active }"
    >
      {{ sidebarItem.label }}
    </p>
  </div>
</template>

<script lang="ts">

import { Component, Vue, Prop } from "vue-property-decorator";
import {SidebarItem, SidebarNavItem} from "../../Interfaces";

@Component
export default class Sidebar extends Vue {
  sidebarItems: SidebarItem[];

  public created() {

    this.sidebarItems = [
      {
        label: "First item",
        active: true
      },
      {
        label: "Second item",
        active: false
      }
    ];

    this.handleScroll();
}

  public handleScroll() {
    this.sidebarItems.forEach((sidebarItem: SidebarItem, index) => {
      if (index == 1) {
        sidebarItem.active = true;
      } else {
        sidebarItem.active = false;
      }
    });
  }
}
</script>

如果我在窗口事件中调用“handleScroll”,反应性就会丢失。

改变

public created() {
  ...
  this.handleScroll();
}

public created() {
  ...
  window.addEventListener("scroll", this.handleScroll);
}

不起作用。该方法已执行,但模板中的反应性丢失。

问题:如何在全局窗口事件中设置这些属性并将它们分配回视图?

4

4 回答 4

1

可能是 Vue 反应性问题。

请尝试通过使用创建深层副本来更改对象引用JSON.parse(JSON.stringify())

public handleScroll() {
  this.sidebarItems.forEach((sidebarItem: SidebarItem, index) => {
    if (index == 1) {
      sidebarItem.active = true;
    } else {
      sidebarItem.active = false;
    }
  });
  this.sidebarItems = JSON.parse(JSON.stringify(this.sidebarItems))
}
于 2019-04-26T01:35:53.410 回答
1

尝试使用 Vue.set 设置值,如警告部分所述,如下所示:

Vue.set(sidebarItems[index], 'active', true)

或者

Vue.set(sidebarItems, index, { ...sidebarItems[index], { active: true})
于 2019-04-26T14:12:37.850 回答
0

仅基于此处显示的代码,这没有明显的充分理由不起作用。Vue 的反应性警告是关于添加/删除数组项,而不是更改属性。

我会通过一些 console.log 确保该方法实际上正在运行中:

this.sidebarItems.forEach((sidebarItem: SidebarItem, index) => {
  if (index == 1) {
    sidebarItem.active = true;
    console.log('on: ' + sidebarItem)
  } else {
    sidebarItem.active = false;
    console.log('off: ' + sidebarItem)
  }
});

如果那没有给出您的答案,最好在 jsfiddle 中重新创建您的问题。这可能会告诉你你需要什么。如果没有,您可以在此处发布小提琴。

于 2019-04-26T02:19:49.607 回答
0

您必须使用计算属性或直接从 vue 调用的函数以反映更改。下面的代码应该工作 -

<template>
  <div class="c-sidebar">
    <p
      v-for="(sidebarItem, index) in sidebarItems"
      :key="index"
      :class="getActiveClass(index)"
    >
      {{ sidebarItem.label }}
    </p>
  </div>
</template>

<script lang="ts">

import { Component, Vue, Prop } from "vue-property-decorator";
import {SidebarItem, SidebarNavItem} from "../../Interfaces";

@Component
export default class Sidebar extends Vue {
  sidebarItems: SidebarItem[];

  public created() {

    this.sidebarItems = [
      {
        label: "First item",
        active: true
      },
      {
        label: "Second item",
        active: false
      }
    ];
}

  public getActiveClass(index: number) {
    return index === 1 ? 'active': '';
  }
}
</script>
于 2019-04-26T03:48:32.707 回答