反应性:更改数组中的 属性,应用于 window 事件
Reactivity: change property in array, applied on window event
简单用例:
特定元素应通过将 属性 "active" 设置为 true (v-bind:class) 来激活 class。
属性 "active" 在 foreach 循环中设置,在检查一些条件后,在方法 "handleScroll".
中
如果我在创建的生命周期中直接调用 "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>
如果我从 window 事件中调用 "handleScroll",反应性就会丢失。
改变
public created() {
...
this.handleScroll();
}
到
public created() {
...
window.addEventListener("scroll", this.handleScroll);
}
不起作用。该方法已执行,但模板中的反应性丢失。
问题:如何在全局 window 事件中设置这些属性并将它们分配回视图?
可能是 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))
}
仅根据此处显示的代码,没有明显充分的理由认为这行不通。 Vue 的反应性警告是关于 adding/removing 数组项,而不是更改属性。
我会三重确保该方法实际上是 运行,其中一些 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 中重现您的问题。这可能会告诉你你需要什么。如果没有,您可以在此处 post fiddle。
您必须使用计算 属性 或直接从 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>
尝试使用 Vue.set 设置值,如 caveats 部分所述,如下所示:
Vue.set(sidebarItems[index], 'active', true)
或
Vue.set(sidebarItems, index, { ...sidebarItems[index], { active: true})
简单用例: 特定元素应通过将 属性 "active" 设置为 true (v-bind:class) 来激活 class。 属性 "active" 在 foreach 循环中设置,在检查一些条件后,在方法 "handleScroll".
中如果我在创建的生命周期中直接调用 "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>
如果我从 window 事件中调用 "handleScroll",反应性就会丢失。
改变
public created() {
...
this.handleScroll();
}
到
public created() {
...
window.addEventListener("scroll", this.handleScroll);
}
不起作用。该方法已执行,但模板中的反应性丢失。
问题:如何在全局 window 事件中设置这些属性并将它们分配回视图?
可能是 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))
}
仅根据此处显示的代码,没有明显充分的理由认为这行不通。 Vue 的反应性警告是关于 adding/removing 数组项,而不是更改属性。
我会三重确保该方法实际上是 运行,其中一些 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 中重现您的问题。这可能会告诉你你需要什么。如果没有,您可以在此处 post fiddle。
您必须使用计算 属性 或直接从 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>
尝试使用 Vue.set 设置值,如 caveats 部分所述,如下所示:
Vue.set(sidebarItems[index], 'active', true)
或
Vue.set(sidebarItems, index, { ...sidebarItems[index], { active: true})