無盡 發表於 2024-9-29 10:36:00

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

<h1 id="背景">背景</h1>
<p>由于业务,需要做一个循环切换的轮播图效果,循环展示列表中的每个item,但是由于切换(从左往右移动,遇到末尾则跳到开头)的过程中可能会删掉当前元素,所以需要更新下标后再切换。由于涉及到几个临界条件,这里列出来处理方式,以便后续参考。</p>
<h1 id="情况分析">情况分析</h1>
<p>一共有两大类:<code>保留</code>(不删除当前元素,直接更新指针),<code>不保留</code>(删除这个元素,更新list,然后根据规则进行更新指针)</p>
<h2 id="1-不保留当前项">1. 不保留当前项</h2>
<p>splice后,数组长度更新了,有以下的情况:</p>
<ol>
<li><strong>新列表长度为1</strong>:那么让<code>current</code>为0,<code>prev</code>和<code>next</code>为null即可。</li>
<li><strong>新列表长度为2</strong>:<code>prev</code> 指向1,<code>current</code> 设置为0,<code>next</code> 为 <code>null</code>。</li>
<li><strong>新列表长度为3</strong>:<code>prev</code> 为2,<code>current</code> 为0,<code>next</code> 为1。<strong>(这个不写也可以,按照第四种的情况进行处理也是这个结果)</strong></li>
<li><strong>新列表长度大于3</strong>:<br>
41. <strong>current位于list头部</strong>:<code>current</code> 不变仍为<code>0</code>,<code>prev</code> 为 <code>list.length - 1</code>,如果 <code>next</code> 的值与 <code>新的prev</code> 一样,则 <code>next</code> 为 <code>null</code>。<br>
42. <strong>current位于list中间</strong>:<code>current</code> 和 <code>next</code> 移动到下一位,<code>prev</code>不变,如果新的 <code>next</code> 和 <code>prev </code>一样,则 <code>next</code> 为 <code>null</code>。<br>
43. <strong>current位于list尾部</strong>:<code>current</code> 为 <code>list.length - 1</code>,<code>prev</code> 为<code>原prev值 - 1</code>,如果 <code>next</code> 的值和 <code>新的prev</code> 一样,则 <code>next</code> 为 <code>null</code>。</li>
</ol>
<h2 id="2-保留当前项">2. 保留当前项</h2>
<p>数组长度没变化,那么有下面的情况:</p>
<ol>
<li><strong>列表长度为1</strong>:那么让<code>current</code>为0,<code>prev</code>和<code>next</code>为null即可。</li>
<li><strong>列表长度为2</strong>:切换顺序,<code>prev</code> 和 <code>current</code> 对调,<code>next</code> 为 <code>null</code>。</li>
<li><strong>列表长度大于2</strong>:
<ul>
<li><code>prev</code>: 变为 <code>原current</code> 的值;</li>
<li><code>current</code>: 变为 <code>原next</code> 的值;</li>
<li><code>next</code>:<code>原next值 + 1</code> 后是否触达数组末尾,若是则设为 <code>0</code>,不是则设为 <code>原next值 + 1</code>。</li>
</ul>
</li>
</ol>
<h1 id="代码">代码</h1>
<p>这里给出的简化过后的代码:</p>
<pre><code class="language-JAVASCRIPT">&lt;template&gt;
&lt;el-switch v-model="isHold" label="保留"&gt;&lt;/el-switch&gt;
&lt;el-button @click="handleIndexSwitch()"&gt;切换&lt;/el-button&gt;
&lt;/template&gt;

&lt;script setup&gt;
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(() =&gt; {
getList();
});

function getList() {
getListApi().then((res) =&gt; {
    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;
});
}

/**
* 处理请求列表的切换 (保留|不保留)
*/
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;
isHold.value = true;
}
&lt;/script&gt;

</code></pre><br><br>
来源:https://www.cnblogs.com/crispyChicken/p/18439077
頁: [1]
查看完整版本: 前端JS数组指针prev、current、next的实现方式,涉及是否删除当前元素的情况分析