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 @ 2024-09-29 10:36  脆皮鸡  阅读(41)  评论(0编辑  收藏  举报