一 、案例效果
[{a: 1,b:2},{a: 1,b:2}, toggle:true]导致视图不更新且数据没有响应式。这种格式是数组套对象的,之后由于不想在遍历一层数据变成[{a: 1,b:2,toggle:true},{a: 1,b:2,oggle:true} ] ,就直接加在对象后面了【虽然这样写法不对,但是,有另外一种可以达到想到的效果】
二、实际效果
数组会变成在最后一个对象中加入需要的属性,即 [{a: 1,b:2},{ a: 1,b:2,toggle:true}]且具有响应式
三、复盘
如果你的数据结构是一个数组,其中最后一个元素是一个对象,包含 toggle 属性,而你希望修改这个 toggle 属性并让视图响应更新,但发现视图没有更新,这通常是因为 Vue 不能检测到数组索引和对象属性的变化。
在 Vue 2.x 中,Vue 不能自动检测以下变动的数组:
当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:vm.items.length = newLength
对于对象,Vue 不能检测到对象属性的添加或删除。
解决方法:
对于数组,使用 Vue.set 或 vm.
s
e
t
方法来设置项值,或使用数组的
s
p
l
i
c
e
方法。对于对象,如果你在创建实例之后添加新的属性到实例上,你应该使用
V
u
e
.
s
e
t
或
v
m
.
set 方法来设置项值,或使用数组的 splice 方法。 对于对象,如果你在创建实例之后添加新的属性到实例上,你应该使用 Vue.set 或 vm.
set方法来设置项值,或使用数组的splice方法。对于对象,如果你在创建实例之后添加新的属性到实例上,你应该使用Vue.set或vm.set。
针对你的情况,如果你想修改数组中最后一个对象的 toggle 属性并确保视图更新,你应该使用 Vue.set 或 vm.$set。假设你的数组存储在 data 的 myArray 属性中,你可以这样做:
// 假设你想切换最后一个元素的 toggle 属性
this.$set(this.myArray[this.myArray.length - 1], 'toggle', !this.myArray[this.myArray.length - 1].toggle);
这样,Vue 就能够检测到 toggle 属性的变化,并且更新视图。
四、完整示例
<template>
<div>
<div v-for="(item, index) in myArray" :key="index">
<!-- 假设你想展示每个对象的 toggle 状态 -->
<p v-if="typeof item.toggle !== 'undefined'">Toggle: {{ item.toggle }}</p>
</div>
<button @click="toggleLastItem">切换最后一项的 Toggle</button>
</div>
</template>
<script>
export default {
data() {
return {
myArray: [{}, {}, { toggle: true }],
};
},
methods: {
toggleLastItem() {
let lastIndex = this.myArray.length - 1;
this.$set(this.myArray[lastIndex], 'toggle', !this.myArray[lastIndex].toggle);
},
},
};
</script>
在这个示例中,点击按钮会切换数组最后一个对象的 toggle 属性值,并且视图会相应地更新
五、应用场景
超过两条展示 展开收起
针对特定的数据结构,如 [{},{}, {toggle: true}],如果数组长度超过两条数据时,需要展示“展开/收起”按钮,并根据 toggle 属性的值动态展示全部数据或只展示前两条数据,可以通过以下步骤实现:
- 计算属性或者封装方法:创建一个计算属性来决定基于 toggle 状态展示的数据。
- 方法:实现一个方法来切换 toggle 状态。
- 模板:在模板中使用计算属性来展示数据,并添加一个按钮来控制展开/收起。
示例代码如下:
<template>
<div>
<!-- 根据 需要循环的数组 展示数据 -->
<div v-for="(item, index) in toggleArrLength(需要循环的数组)" :key="index">
<!-- 展示每个项目的内容 -->
{{ item.content }}
</div>
<!-- 当数组长度超过2时,展示展开/收起按钮 -->
<button v-if="items.length > 2" @click="toggleHandle(需要循环的数组)">
{{ 需要循环的数组[需要循环的数组.length - 1].toggle ? '收起' : '展开' }}
</button>
</div>
</template>
private toggleArrLength(arrData: any) {
let lastIndex = arrData.length - 1;
return arrData[lastIndex].toggle ? arrData : arrData.slice(0, 2);
}
// 切换 toggle 状态
private toggleHandle(data) {
console.log('toggleMsg--item', data);
let lastIndex = data.length - 1;
this.$set(
data[lastIndex],
'toggle',
!data[lastIndex].toggle,
);
}
样例
<template>
<div>
<!-- 根据 displayedItems 展示数据 -->
<div v-for="(item, index) in displayedItems" :key="index">
<!-- 展示每个项目的内容 -->
{{ item.content }}
</div>
<!-- 当数组长度超过2时,展示展开/收起按钮 -->
<button v-if="items.length > 2" @click="toggleItems">
{{ items[items.length - 1].toggle ? '收起' : '展开' }}
</button>
</div>
</template>
<script>
export default {
data() {
return {
// 假设的数据结构,最后一个对象包含 toggle 属性
items: [{ content: 'Item 1' }, { content: 'Item 2' }, { toggle: true }],
};
},
computed: {
// 根据 toggle 状态决定展示的数据
displayedItems() {
// 如果 toggle 为 true 或数组长度不超过2,展示全部项目
if (this.items.length <= 2 || this.items[this.items.length - 1].toggle) {
return this.items.slice(0, -1); // 不包括最后一个 toggle 对象
} else {
// 否则,只展示前两个项目
return this.items.slice(0, 2);
}
},
},
methods: {
// 切换 toggle 状态
toggleItems() {
let toggleItem = this.items[this.items.length - 1];
toggleItem.toggle = !toggleItem.toggle;
},
},
};
</script>
结论: 在这个示例中:
items 数组包含了要展示的数据,最后一个对象是控制展开/收起的 toggle 状态。
displayedItems 计算属性根据 toggle 的值决定展示全部数据还是只展示前两条数据。
toggleItems 方法用于切换 toggle 状态。
模板中使用 v-for 根据 displayedItems 展示数据,并提供一个按钮来控制展开/收起,按钮的文本也根据 toggle 状态动态变化。
注意:这个示例假设除了最后一个对象用于控制展开/收起外,其他对象都是要展示的数据。如果你的数据结构有所不同,请相应调整代码。