第五届字节跳动青训营 前端进阶学习笔记(二)JavaScript编码规范

1.前言

本次课程主要讲解了有关JavaScript编码原则和代码优化的相关问题。

重点内容:

  • HTML、CSS、JS各司其责
  • 具备正确性、扩展性、复用性的组件封装
  • 函数式编程思想
  • 代码优化

2.写好JS的一些基本原则

  • 各司其责
  • 组件封装
  • 过程抽象

各司其责

首先,良好的前端代码应该是HTML、CSS和JS三部分代码各司其责的,也就是各自控制各自所负责的部分。主要需要注意以下几点:

  • 避免不必要的由JS直接操作CSS
  • 使用class来切换样式而不是修改style
  • 能单独使用CSS实现的样式,尽量使用CSS,追求纯展示性内容0JS

比如在下面的一个例子中:

image.png

我们来实现一个深色模式切换的功能,通常会按照下面这种形式实现

image.png

这样当我们点击切换按钮的时候,页面就会切换到深色模式显示。

image.png

但是上述代码还存在很强的优化空间,首先,我们可以通过class来优化这一过程,减少DOM的操作次数。
image.png image.png

此外,我们还能使用纯CSS的方法来实现这一功能。借助label标签和:checked伪类的特性,我们在不借助JS代码的情况下,实现了切换界面深浅主题的功能。

image.png image.png

组件封装

组件设计的基本原则:封装性、正确性、扩展性、复用性

下面我们来封装一个轮播图组件

  • HTML结构:

image.png

  • CSS样式:

image.pngalt="image.png" />

- JS代码:

image.png
首先,构建轮播图组件的基本结构、展现效果和行为。

image.png
下一步,我们开始构建轮播图的控件,轮播图控件我们通过自定义事件的方式来控制原点控制的状态切换,以此来与轮播图组件解耦。

image.png

image.png
这里,我们在Silder的构造函数里,定义控件的方法。并且新增了start和stop方法,用来实现具体的控件行为。

class Slider {
      constructor(id, delay=3000) {
        this.container = document.querySelector(`#${id}`);
        this.sliders = document.querySelectorAll('.slider__item, .slider__item--selected');
        this.delay = delay;

        const controlContainer = document.querySelector('.slider__control');
        if(controlContainer) {
          const controls = document.querySelectorAll('.slider__control-item, .slider__control-item--selected');
          controlContainer.addEventListener('mouseover', evt=> {
            const idx = Array.from(controls).indexOf(evt.target);
            if(idx >= 0) {
              this.toslider(idx);
              this.stop();
            }
          });

          controlContainer.addEventListener('mouseout', evt=> {
            this.start();
          })

          this.container.addEventListener('silde', evt => {
            const idx = evt.detail.index;
            const selected = document.querySelector('.slider__control-item--selected');
            if(selected) {
              selected.className = 'slider__control-item';
            } 
            controls[idx].className && (controls[idx].className = 'slider__control-item--selected');
          })
        }

        const pre = document.querySelector('.slider__control--previouse');
        if(pre) {
          pre.addEventListener('click', evt => {
            this.stop();
            this.preslider();
            this.start();
            evt.preventDefault();
          })
        }
        
        const next = document.querySelector('.slider__control--next');
        if(next) {
          next.addEventListener('click', evt => {
            this.stop();
            this.nexslider();
            this.start();
            evt.preventDefault();
          })
        }
        
      }
      getCurrent() {
        const current = document.querySelector('.slider__item--selected');
        return current;
      }
      getCurrentIndex() {
        return Array.from(this.sliders).indexOf(this.getCurrent());
      }
      toslider(idx) {
        const current = this.getCurrent();
        if(current) {
          current.className = 'slider__item';
        }
        this.sliders[idx] && (this.sliders[idx].className = 'slider__item--selected');

        const detail = {
          index: idx
        };
        const event = new CustomEvent('silde', {bubbles: true, detail});
        this.container.dispatchEvent(event);
      }
      preslider() {
        const idx = this.getCurrentIndex();
        this.toslider((this.sliders.length + idx - 1) % this.sliders.length);
      }
      nexslider() {
        const idx = this.getCurrentIndex();
        this.toslider((idx + 1) % this.sliders.length);
      }
      start() {
        this.stop();
        this.timer = setInterval(()=>this.nexslider(), this.delay);
      }
      stop() {
        clearInterval(this.timer);
      }
    }

至此一个基本的轮播图组件就封装完毕了。

image.png

在上面的实现过程中,我们在Slider类的构造函数中,定义了各个控件的所有行为,因此各控件的行为和Silder组件是高度耦合的。对此,我们需要将各个控件的行为单独封装为插件,然后通过安装插件的方式,将插件安装在组件上,以此来实现解耦。同时,若日后我们需要增加控件时,只需要添加相应的控件插件就行了。

image.png

image.png

image.png

image.png

在此基础上,我们还可以进一步对模板进行封装,即将控件对应的HTML代码也封装进插件中。

image.png

这样封装好之后,我们只需要一组HTML标签,就能展示整个轮播图组件了。

image.png

过程抽象

过程抽象就是利用函数式编程的思想来处理局部细节控制的一些方法。

  • 高阶函数

    • 以函数作为参数
    • 以函数作为返回值
    • 常用于作为函数装饰器
  • 常用高阶函数

    • Once
    • Throttle
    • Consumber
    • Iterative
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

volit_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值