首页 > 解决方案 > 如何将此程序脚本转换为工厂或构造函数?

问题描述

所以,这是一个简单的计数器脚本:

//variables
let counter = document.querySelector('.counter');
let decrementCounter = document.querySelector('.decrement-counter');
let incrementCounter = document.querySelector('.increment-counter');
let count = 0;

//event listeners
decrementCounter.addEventListener('click', minusCounter);
incrementCounter.addEventListener('click', plusCounter);

function plusCounter() {
  count++;
  counter.innerHTML = count;
  if (counter.innerHTML > '0') {
    counter.style.color = 'green';
  } else if (counter.innerHTML === '0') {
    counter.style.color = 'black';
  }
}

function minusCounter() {
  count--;
  counter.innerHTML = count;
  if (counter.innerHTML < '0') {
    counter.style.color = 'red';
  } else if (counter.innerHTML === '0') {
    counter.style.color = 'black';
  }
}
body {
  margin: 0;
  padding: 0;
  display: flex;
  height: 100vh;
  justify-content: center;
  align-items: center;
}
<body>
  <div class="counter">
    <p>0</p>
  </div>
  <button class="decrement-counter">Decrement</button>
  <button class="increment-counter">Increment</button>
</body>

(忽略不良设计,仅用于测试目的)

我想做相同的脚本,但使用构造函数/工厂函数。或者只是一个简单的对象(封装)。

也许我错过了一些重要的东西,这就是我失败的原因,有人可以给我举个例子吗?

标签: javascript

解决方案


正如评论中提到的,有点不清楚您正在寻找什么样的封装,但这里是将您的代码简单地重构为一个函数,该函数接受一个容器元素并返回一个对象,该对象包含对set()实例化计时器功能的函数的引用该元素的子元素,以及cleanup()删除实例化的函数。

它要求容器中存在必要的组成元素,但您可以对此进行扩展,以在函数内完全构建计时器,或者至少对元素的存在进行一些检查,以免在缺少元素时中断。

const setCounter = (element) => {
  //variables
  const decrementCounter = element.querySelector('.decrement-counter');
  const incrementCounter = element.querySelector('.increment-counter');
  const output = element.querySelector('.output');
  let count = 0;

  function plusCounter () {
    count++;
    output.innerHTML = count;
    if (output.innerHTML > '0') {
        output.style.color = 'green';
    } else if (output.innerHTML === '0') {
        output.style.color = 'black';
    }
  }

  function minusCounter () {
    count--;
    output.innerHTML = count;
    if (output.innerHTML < '0') {
        output.style.color = 'red';
    } else if (output.innerHTML === '0') {
        output.style.color = 'black';
    }
  }
  
  const set = () => {
    decrementCounter.addEventListener('click', minusCounter);
    incrementCounter.addEventListener('click', plusCounter);
    element.classList.add('active');
  }
  
  const cleanup = () => {
    
    decrementCounter.removeEventListener('click', minusCounter);
    incrementCounter.removeEventListener('click', plusCounter);
    count = 0;
    output.innerHTML = "0";
    output.style.color = 'black';
    element.classList.remove('active');
  }
  
  return {
    set: set,
    cleanup: cleanup,
  }
}

const counter = setCounter(document.getElementById('counter-1'));
document.querySelector('.set-counter1').addEventListener('click', counter.set);
document.querySelector('.cleanup-counter1').addEventListener('click', counter.cleanup);

const counter2 = setCounter(document.getElementById('counter-2'));
document.querySelector('.set-counter2').addEventListener('click', counter2.set);
document.querySelector('.cleanup-counter2').addEventListener('click', counter2.cleanup);
body {
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;

    justify-content: center;
    align-items: center;
}

.output {
  text-align: center;
  background-color: white;
  width: 2rem;
  margin: 1rem auto;
 }
 
 .counter-control {
  width: 100vw;
  text-align: center;
  padding: 8px;
 }
 
 .active {
  background-color: aquamarine;
 }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="css.css" type="text/css">
    <title>Document</title>
</head>
<body>
    <div id="counter-1" class="counter">
     <p class="output">0</p>

    <button class="decrement-counter">Decrement</button>
    <button class="increment-counter">Increment</button>
    </div>
    <div class="counter-control">
      <button class="set-counter1">Set Counter</button>
      <button class="cleanup-counter1">Cleanup Counter</button>
    </div>
    <div id="counter-2" class="counter">
     <p class="output">0</p>

    <button class="decrement-counter">Decrement</button>
    <button class="increment-counter">Increment</button>
    </div>
    <div class="counter-control">
      <button class="set-counter2">Set Counter</button>
      <button class="cleanup-counter2">Cleanup Counter</button>
    </div>
</body>
</html>


推荐阅读