一 、案例效果
[{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 状态动态变化。
注意:这个示例假设除了最后一个对象用于控制展开/收起外,其他对象都是要展示的数据。如果你的数据结构有所不同,请相应调整代码。