如何写好JS|青训营

97 阅读4分钟

只能说真的老师是讲的非常深入....有些点我也不太好理解

class1-各司其职(深夜食堂案例)

这个案例的需求是点击按钮实现网页内容的夜间模式和正常模式的切换,挺常见的一个场景哈.

方案一: 点击按钮直接用js操作css的样式

方案二: 在css中提前定义好夜间模式的样式,点击按钮之后用js操作类名.(这个是比较常规的做法)

方案三: 纯css实现.

正如老师所讲前端需要做到结构表现行为分离,不然不利于维护且性能也一言难尽...所以方案一这种很蠢的做法自己写写就好了,工作中写出来肯定会被骂.方案二,还好,如果需要考虑兼容性的话,那是一个不错的选择.方案三的话在不考虑兼容性的情况下是最优解.

这边我自己搭一个demo试试(非常简陋的,但是意思在这里哈)

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>深夜食堂</title>
  <style>
    #modeCheckBox {
      display: none;
    }
    #modeBtn::after {
      /* 这下面就是放字体图标的地方,大家自行了解 */
      content: "白天模式";
    }
    #modeCheckBox:checked + .content {
      background: #000;
      color: white;
      transition: all 1s;
    }
    #modeCheckBox:checked + .content #modeBtn::after {
      content: "夜间模式";
    }
    #modeBtn {
      font-size: 2rem;
      float: right;
    }
  </style>
</head>
<body>
  <input type="checkbox" name="" id="modeCheckBox">
  <div class="content">
    <header>
      <label for="modeCheckBox" id="modeBtn"></label>
      <!-- 太阳和月亮以伪元素的形势放到这里,这里我直接放文字,懒得找字体图标了. -->
      <h1>深夜食堂</h1>
    </header>
    <main>
      <!-- 这边没图,不放图了 -->
      <div><img src="" alt="没有图片"></div>
      <div class="description">
        <p>这是一间营业时间从午夜十二点到早上七点的特殊食堂.........</p>
      </div>
    </main>
  </div>
</body>
</html>

效果如下:(我不会做动图,这个是能正常切换的,大家意会)

day4-demo-1.png

day4-demo-2.png

大家自己可以去试一下,复制我的代码是能跑出相同效果的,不需要其他配置

class2-组件封装(轮播图案例)

这个组件封装呢,其实听到后面我都觉得像是在讲框架源码了(不知道是不是我的错觉),我之前也写过轮播图组件...但是比较屎山.

我跟着老师的代码自己实现了一下,那个轮播图上的小圈圈和左右的箭头挺丑的,大家,看看就好.

如果你要copy代码你要注意找自己的图片,然后注意调整my-slider容器的宽高. 这个不是最终版的,最终版的我还在debugger,有点小问题,大家这个凑合看.

 <div id="my-slider" class="slider-list">
    <ul>
      <li class="slider-list__item--selected">
        <img src="./images/dw.png" alt="">
      </li>
      <li class="slider-list__item">
        <img src="./images/sw.png" alt="">
      </li>
      <li class="slider-list__item">
        <img src="./images/uw.png" alt="">
      </li>
      <li class="slider-list__item">
        <img src="./images/ww.png" alt="">
      </li>
      <li class="slider-list__item">
        <img src="./images/shiw.png" alt="">
      </li>
      <li class="slider-list__item">
        <img src="./images/yw.png" alt="">
      </li>
    </ul>
    <a class="slide-list__next">&gt;</a>
          <a class="slide-list__previous">&lt;</a>
          <div class="slide-list__control">
            <span class="slide-list__control-buttons--selected"></span>
            <span class="slide-list__control-buttons"></span>
            <span class="slide-list__control-buttons"></span>
            <span class="slide-list__control-buttons"></span>
            <span class="slide-list__control-buttons"></span>
            <span class="slide-list__control-buttons"></span>
          </div>
  </div>

css:

* {
  padding: 0;
  margin: 0;
}

#my-slider {
  position: relative;
  width: 490px;
  height: 616px;
  margin: 100px auto;
}

.slider-list ul {
  list-style-type: none;
  position: relative;
  padding: 0;
  margin: 0;
}

.slider-list__item,
.slider-list__item--selected {
  position: absolute;
  transition: opacity 1s;
  opacity: 0;
  text-align: center;
}

.slider-list__item--selected {
  transition: opacity 1s;
  opacity: 1;
}

.slide-list__control {
  position: absolute;
  bottom: 9px;
  left: 50%;
  display: flex;
  transform: translateX(-50%);
}

.slide-list__control-buttons,
.slide-list__control-buttons--selected {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  margin: 0 5px;
  background-color: #ccc;
}

.slide-list__control-buttons--selected {
  background-color: #f25353;
}

.slide-list__previous {
  position: absolute;
  top: 50%;
  left: 1%;
  font-size: 20px;
}

.slide-list__next {
  position: absolute;
  top: 50%;
  right: 1%;
  font-size: 20px;
}

js

class Slider {

 constructor(id, cycle = 3000) {
      this.container = document.getElementById(id);
      this.items = this.container.querySelectorAll('.slider-list__item, .slider-list__item--selected');
      this.cycle = cycle;
 }

 registerPlugins(...plugins) {
      plugins.forEach(plugin => plugin(this))
 }
​
 getSelectedItem() {
​
  const selected = this.container
​
   .querySelector('.slider-list__item--selected');
​
  return selected
​
 }
​
 getSelectedItemIndex() {
​
  return Array.from(this.items).indexOf(this.getSelectedItem());
​
 }
​
 slideTo(idx) {
​
  const selected = this.getSelectedItem();
​
  if (selected) {
​
   selected.className = 'slider-list__item';
​
  }
​
  const item = this.items[idx];
​
  if (item) {
​
   item.className = 'slider-list__item--selected';
​
  }
​
  const detail = { index: idx }
​
  const event = new CustomEvent('slide', { bubbles: true, detail })
​
  slider.container.dispatchEvent(event)
​
 }
​
 slideNext() {
​
  const currentIdx = this.getSelectedItemIndex();
​
  const nextIdx = (currentIdx + 1) % this.items.length;
​
  this.slideTo(nextIdx);
​
 }
​
 slidePrevious() {
​
  const currentIdx = this.getSelectedItemIndex();
​
  const previousIdx = (this.items.length + currentIdx - 1)
​
   % this.items.length;
​
  this.slideTo(previousIdx);
​
 }
​
 addEventListener(type, handler) {
​
  this.container.addEventListener(type, handler)
​
 }
​
 start() {
​
  this.stop()
​
  this._timer = setInterval(() => {
​
   this.slideNext()
​
  }, this.cycle)
​
 }
​
 stop() {
​
  clearInterval(this._timer)
​
 }
​
}
​
function pluginController(slider) {
​
 const controller = slider.container.querySelector('.slide-list__control');
​
 if (controller) {
​
  const buttons = controller.querySelectorAll('.slide-list__control-buttons, .slide-list__control-buttons--selected');
​
  controller.addEventListener('mouseover', evt => {
​
   const idx = Array.from(buttons).indexOf(evt.target);
​
   if (idx >= 0) {
          slider.slideTo(idx);
          slider.stop();
   }
​
  });
​
  controller.addEventListener('mouseout', evt => {
​
   slider.start();
​
  });
​
  slider.addEventListener('slide', evt => {
​
   const idx = evt.detail.index
​
   const selected = controller.querySelector('.slide-list__control-buttons--selected');
​
   if (selected) selected.className = 'slide-list__control-buttons';
​
   buttons[idx].className = 'slide-list__control-buttons--selected';
​
  });
​
 }
​
}
​
function pluginPrevious(slider) {
​
 const previous = slider.container.querySelector('.slide-list__previous');
​
 if (previous) {
​
  previous.addEventListener('click', evt => {
​
   slider.stop();
​
   slider.slidePrevious();
​
   slider.start();
​
   evt.preventDefault();
​
  });
​
 }
​
}
​
function pluginNext(slider) {
​
 const next = slider.container.querySelector('.slide-list__next');
​
 if (next) {
​
  next.addEventListener('click', evt => {
​
   slider.stop();
​
   slider.slideNext();
​
   slider.start();
​
   evt.preventDefault();
​
  });
​
 }
​
}
​
const slider = new Slider('my-slider');
​
slider.registerPlugins(pluginController, pluginPrevious, pluginNext)
​
slider.start()

class3-节流与高阶函数

概念引入 ---纯函数: 无论何时调用结果都确定

纯函数举例:

function add(x,y) {
    return x + y
}

无论什么情况下 我 add(2,3) 他的结果都是5

非纯函数举例:

let idx = 0function count() {
    return ++idx
}

我们可以看到 第一次count() 得1 第二次得2...总之就是 每次调用 虽然都是count()同样的代码 但是结果不一样.这就是非纯函数

为什么节流推荐使用高阶函数?

因为使用高阶函数能减少非纯函数的数量,方便代码的测试以及提高代码质量.

节流函数举例:

function throttle(fn,t) {
    let timer = null
    return function() {
      if (!timer) {
      timer = setTimeout(() => {
        fn()
        timer = null
      },t)
    }
    }
   }

概念拓展:编程语言的编程范式

命令式: 包括面向过程和面向对象.倾向于怎么做.

声明式: 包括逻辑式和函数式.倾向于做什么.

未完待续...