JavaScript 30天编码挑战——第 10 天

369 阅读4分钟

这是我参与更文挑战的第12天,活动详情查看: 更文挑战

Hold Shift to Check Multiple Checkboxes

这个模块的主要实现的是通过操控键盘按键去实现按下 shift 按键之后实现 checkbox 的多选操作的功能。在初始文档中提供了一组类型为 checkbox 的 input 标签,选中某个checkbox 时,其文字会显示删除线效果。我们根据原作者提供的初始化文档,完成之后的实现效果。

一、效果展示

1.index-START.html

1.gif

2.index-FINISHED.html

2.gif

3. 我的效果

动画.gif

二、实现

最终代码

<script>
    ;(function(){
      const checkboxes = Array.from(document.querySelectorAll('.inbox input[type="checkbox"]'));
  
      let lastCheck = null;
  
      function clickHandler(e){
        console.log(e);
        if(this.checked){
          if(e.shiftKey && lastCheck !== null){
            let nowCheck = checkboxes.indexOf(this);
            checkboxes.slice(
              Math.min(nowCheck.lastCheck),
              Math.max(nowCheck,lastCheck)
              )
              .forEach(input => (input.checked = true));
          }
          lastCheck = checkboxes.indexOf(this);  //如果是打钩状态,记录下来
        } else {
          lastCheck = null;  //否则清掉
        }
      }
  
      checkboxes.forEach(input =>{
        input.addEventListener("click",clickHandler);
      })
    })()
  </script>

三、总结回顾

拿到模块的题目,我们首要做一个思考,这部分模块我感觉非常的有意思。

当在键盘上按下 Shift 键进要实现多选操作的时候,我们整个过程应该是怎么样的?我们来还原一下整个过程,顺便剖析一下原作者的解决思路。

  1. 选中某一项(记为 a);

  2. 按下 shift 按键;

  3. 在选中一项(记为 b);

  4. a 和 b 之间的部分都被选中。

整个的过程应该就是这样的了,这是按照描述的操作过程,那么这样我就产生了一些疑问

  • 如果我一开始就按下了 shift 按键呢?

  • 如果我选中了某一项,然后我再取消,然后紧接着按下 shift 按键又会是怎么样的呢?

  • 如果我选中了某一项,并且按下了 shift 按键选中了另外一项,这时候我将 a 和 b 之间的某一项取消选中之后,然后我再次按下 shift 按键之后,选中另外一项(记为 c),这时候包含在 a 和 b 之间的选中部分会被取消选中吗?

0071395A.gif

然后带着这些疑问我就去操作了原作的最终实现效果,然后我发现:

当我刚进入页面没有进行选中某一项,而是直接执行按下 shift 按键的操作的时候,这个时候内容是全部选中的。

3.gif

你看,真是普通且自信。

然后我思考了一下,发现其实一开始我的想法就是——

如果要实现按下 shift 按键的时候,选中 a 和 b 之间的部分,那么就用一个变量,来标记这个范围。将变量初始值为 false,当按下 Shift 键并且同时选中了某个元素的时候,遍历这个范围的所有项,如果遇到 a 或 b,则将标记值取反。同时,将所有标记为 true 的项设置为选中。这时候就实现了我们想要的结果。

未命名文件 (2).png 但是如果这样去操作呢,就会出现一个问题,当进入页面直接选择按住 Shift 再点击某一项,那么这一项之后的元素都会被选中——完求了,一下子思路跨国接轨了,然后还都是有 bug 的。并且,对于取消选中,无法批量操作。

那么,我们就选择用另一种方式(slice)尝试一下吧。

过程分解

1.选中所有 checkbox 元素进行操作。 首先找到所有的类型为 checkbox 的 input 元素,然后进行 Array.from 将其变成一个阵列(为什么这样变化,因为我要用 slice 啊,好整啊...)。

const checkboxes = Array.from(document.querySelectorAll('.inbox input[type="checkbox"]'));

那么 Arrary.from 如何使用呢?

MDN不请自来!

链接地址:developer.mozilla.org/zh-CN/docs/…

image.png 操作之后就变成了这样的形式啦。

  1. 事件监听。
    function clickHandler(e){
      console.log(e);
    }

    checkboxes.forEach(input =>{
      input.addEventListener("click",clickHandler);
    })

这里可以先看一下 clickHandler 方法里的 e 都有哪些属性.

image.png

这样我们就知道我们要操作的就是 shiftKey ,当按住 shift 按键选中某一项的时候,此时 shiftKey 的状态变成了 true。

image.png

  1. 区间 a 的判断。
 let lastCheck = null;

    function clickHandler(e){
      console.log(e);
      if(this.checked){
        lastCheck = checkboxes.indexOf(this);  //如果是打钩状态,记录下来
      } else {
        lastCheck = null;  //否则清掉
      }
    }

    checkboxes.forEach(input =>{
      input.addEventListener("click",clickHandler);
    })
  1. 效果实现:
·let lastCheck = null;
  
      function clickHandler(e){
        console.log(e);
        if(this.checked){
          if(e.shiftKey && lastCheck !== null){
            let nowCheck = checkboxes.indexOf(this);
            checkboxes.slice(
              Math.min(nowCheck.lastCheck),
              Math.max(nowCheck,lastCheck)
              )
              .forEach(input => (input.checked = true));
          }
          lastCheck = checkboxes.indexOf(this);  //如果是打钩状态,记录下来
        } else {
          lastCheck = null;  //否则清掉
        }
      }
  
      checkboxes.forEach(input =>{
        input.addEventListener("click",clickHandler);
      })

这样就已经实现了我们的这个功能:

动画.gif

四、重难点

大概率已经分析到了上边的总结中去做了思考,虽然它出错了片场,但是还是要完美的进行演绎,毕竟——成年人,都不容易!

00721A05.jpg

                                     记得按时学习!