JS数组指针prev、current、next的实现方式,涉及是否删除当前元素的情况分析

背景

由于业务,需要做一个循环切换的轮播图效果,循环展示列表中的每个item,但是由于切换(从左往右移动,遇到末尾则跳到开头)的过程中可能会删掉当前元素,所以需要更新下标后再切换。由于涉及到几个临界条件,这里列出来处理方式,以便后续参考。

情况分析

一共有两大类:保留(不删除当前元素,直接更新指针),不保留(删除这个元素,更新list,然后根据规则进行更新指针)

1. 不保留当前项

splice后,数组长度更新了,有以下的情况:

  1. 新列表长度为1:那么让current为0,prevnext为null即可。
  2. 新列表长度为2prev 指向1,current 设置为0,nextnull
  3. 新列表长度为3prev 为2,current 为0,next 为1。(这个不写也可以,按照第四种的情况进行处理也是这个结果)
  4. 新列表长度大于3
    41. current位于list头部current 不变仍为0prevlist.length - 1,如果 next 的值与 新的prev 一样,则 nextnull
    42. current位于list中间currentnext 移动到下一位,prev不变,如果新的 nextprev 一样,则 nextnull
    43. current位于list尾部currentlist.length - 1prev原prev值 - 1,如果 next 的值和 新的prev 一样,则 nextnull

2. 保留当前项

数组长度没变化,那么有下面的情况:

  1. 列表长度为1:那么让current为0,prevnext为null即可。
  2. 列表长度为2:切换顺序,prevcurrent 对调,nextnull
  3. 列表长度大于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>
posted @   脆皮鸡  阅读(119)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示