<div class="J_calculator">
  <div class="result">0</div>
  <div class="input-group">
    <input type="text" value="0" class="f-input" />
    <input type="text" value="0" class="s-input" />
  </div>
  <div class="btn-group">
    <button data-field="plus" class="current">+</button>
    <button data-field="minus">-</button>
    <button data-field="mul">*</button>
    <button data-field="div">/</button>
  </div>
</div>
.btn-group button.current {
  background-color: orange;
  color: #fff;
}
class Compute {
  plus(a, b) {
    return a + b;
  }
  minus(a, b) {
    return a - b;
  }
  mul(a, b) {
    return a * b;
  }
  div(a, b) {
    return a / b;
  }
}

// 通过继承 Compute 获取计算方法
class Calculator extends Compute {
  constructor(doc) {
    super();
    // 获取容器
    const oCal = doc.getElementsByClassName('J_calculator')[0];
    // 获取两个input
    this.fInput = oCal.getElementsByTagName('input')[0];
    this.sInput = oCal.getElementsByTagName('input')[1];
    // 获取按钮
    this.oBtnGroup = oCal.getElementsByClassName('btn-group')[0];
    this.oBtnItems = this.oBtnGroup.getElementsByTagName('button');
    // 获取结果
    this.oResult = oCal.getElementsByClassName('result')[0];
    // 处理数据
    this.data = {
      // fNumber: xxx,
      // sNumber: xxx,
      // field: 'plus'
    };
    this.data = this.defineData();
    // field 高亮状态
    this.btnIdx = 0;
  }
  init() {
    this.bindEvent();
  }
  bindEvent() {
    this.oBtnGroup.addEventListener('click', this.onFieldBtnClick.bind(this), false);
    this.fInput.addEventListener('input', this.onNumberInput.bind(this), false);
    this.sInput.addEventListener('input', this.onNumberInput.bind(this), false);
  }
  defineData() {
    let _obj = {},
        fNumber = 0,
        sNumber = 0,
        field = 'plus';

    const _self = this;

    Object.defineProperties(_obj, {
      fNumber: {
        // get 返回值
        get() {
          console.log('"fNumber" is being got.');
          return fNumber;
        },
        // set监听值的改变,然后刷新视图
        set(newVal) {
          fNumber = newVal;
          _self.computeResult(fNumber, sNumber, field);
          console.log(`The value "fNumber" has been changed. [${fNumber}]`);
        }
      },
      sNumber: {
        get() {
          console.log('"sNumber" is being got.');
          return sNumber;
        },
        set(newVal) {
          sNumber = newVal;
          _self.computeResult(fNumber, sNumber, field);
          console.log(`The value "sNumber" has been changed. [${sNumber}]`);
        }
      },
      field: {
        get() {
          console.log('"field" is being got.');
          return field;
        },
        set(newVal) {
          field = newVal;
          _self.computeResult(fNumber, sNumber, field);
          console.log(`The value "field" has been changed. [${field}]`);
        }
      }
    });

    return _obj;
  }

  // 监听计算方式按钮
  onFieldBtnClick(ev) {
    const e = ev || window.event,
          tar = e.target || e.srcElement,
          tagName = tar.tagName.toLowerCase();

    tagName === 'button' && this.fieldUpdate(tar);
  }
  // 监听input变化
  onNumberInput(ev) {
    const e = ev || window.event,
          tar = e.target || e.srcElement,
          className = tar.className,
          val = Number(tar.value.replace(/\s+/g, '')) || 0;

    switch (className) {
      case 'f-input':
        this.data.fNumber = val;
        break;
      case 's-input':
        this.data.sNumber = val;
      default:
        break;
    }
  }
  // 更新 field 以及样式
  fieldUpdate(target) {
    this.oBtnItems[this.btnIdx].className = '';
    this.btnIdx = [].indexOf.call(this.oBtnItems, target);
    target.className += ' current';
    this.data.field = target.getAttribute('data-field');
  }
  // 更新视图
  computeResult(fNumber, sNumber, field) {
    this.oResult.innerText = this[field](fNumber, sNumber);
  }
}

new Calculator(document).init();

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.