JS数组指针prev、current、next的实现方式,涉及是否删除当前元素的情况分析
背景
由于业务,需要做一个循环切换的轮播图效果,循环展示列表中的每个item,但是由于切换(从左往右移动,遇到末尾则跳到开头)的过程中可能会删掉当前元素,所以需要更新下标后再切换。由于涉及到几个临界条件,这里列出来处理方式,以便后续参考。
情况分析
一共有两大类:保留
(不删除当前元素,直接更新指针),不保留
(删除这个元素,更新list,然后根据规则进行更新指针)
1. 不保留当前项
splice后,数组长度更新了,有以下的情况:
- 新列表长度为1:那么让
current
为0,prev
和next
为null即可。 - 新列表长度为2:
prev
指向1,current
设置为0,next
为null
。 - 新列表长度为3:
prev
为2,current
为0,next
为1。(这个不写也可以,按照第四种的情况进行处理也是这个结果) - 新列表长度大于3:
41. current位于list头部:current
不变仍为0
,prev
为list.length - 1
,如果next
的值与新的prev
一样,则next
为null
。
42. current位于list中间:current
和next
移动到下一位,prev
不变,如果新的next
和prev
一样,则next
为null
。
43. current位于list尾部:current
为list.length - 1
,prev
为原prev值 - 1
,如果next
的值和新的prev
一样,则next
为null
。
2. 保留当前项
数组长度没变化,那么有下面的情况:
- 列表长度为1:那么让
current
为0,prev
和next
为null即可。 - 列表长度为2:切换顺序,
prev
和current
对调,next
为null
。 - 列表长度大于2:
prev
: 变为原current
的值;current
: 变为原next
的值;next
:原next值 + 1
后是否触达数组末尾,若是则设为0
,不是则设为原next值 + 1
。
代码
这里给出的简化过后的代码:
<template>
<el-switch v-model="isHold" label="保留"></el-switch>
<el-button @click="handleIndexSwitch()">切换</el-button>
</template>
<script setup>
import { ref, onMounted } from "vue";
import { getListApi } from "@/api/list";
const isHold = ref(false); // 页面里面有个开关,是否在切换后删除当前item
const list = ref([]);
const currentItem = ref();
const INDEX = ref({
prev: null,
current: null,
next: null,
});
onMounted(() => {
getList();
});
function getList() {
getListApi().then((res) => {
let result = res.data.data;
// 初始化下标
switch (result.length) {
case 1:
INDEX.value = {
prev: null,
current: 0,
next: null,
};
break;
case 2:
INDEX.value = {
prev: 1,
current: 0,
next: null,
};
break;
default:
INDEX.value = {
prev: result.length - 1,
current: 0,
next: 1,
};
break;
}
list.value = result;
currentItem.value = result[INDEX.value.current];
});
}
/**
* 处理请求列表的切换 (保留|不保留)
*/
function handleIndexSwitch() {
if (!list.value.length) return;
/** 不保留,则把当前的item删掉,然后重新计算prev、current和next的指针指向 */
if (!isHold.value) {
// 删除当前项
list.value.splice(INDEX.value.current, 1);
if (list.value.length === 0) {
currentItem.value = null;
getList();
return;
}
switch (list.value.length) {
case 1:
INDEX.value = {
prev: null,
current: 0,
next: null,
};
break;
case 2:
INDEX.value = {
prev: 1,
current: 0,
next: null,
};
break;
case 3:
INDEX.value = {
prev: 2,
current: 0,
next: 1,
};
break;
default:
if (INDEX.value.current === 0) {
INDEX.value = {
prev: list.value.length - 1,
current: 0,
next: 1,
};
} else if (INDEX.value.current === list.value.length - 1) {
INDEX.value = {
prev: INDEX.value.prev - 1,
current: list.value.length - 1,
next: INDEX.value.prev,
};
} else {
INDEX.value = {
prev: INDEX.value.prev,
current: INDEX.value.next,
next:
INDEX.value.next + 1 === list.value.length
? 0
: INDEX.value.next + 1,
};
}
break;
}
} else {
/** 保留,则切换下一个 */
switch (list.value.length) {
case 1:
INDEX.value = {
prev: null,
current: 0,
next: null,
};
break;
case 2:
/** 调换一下顺序? */
INDEX.value = {
prev: INDEX.value.current,
current: INDEX.value.prev,
next: null,
};
break;
default:
INDEX.value = {
prev: INDEX.value.current,
current: INDEX.value.next,
next:
INDEX.value.next + 1 === list.value.length
? 0
: INDEX.value.next + 1,
};
break;
}
}
currentItem.value = list.value[INDEX.value.current];
isHold.value = true;
}
</script>