【问题标题】:What causes the failure to update a template variable in this Vue calculator application?在这个 Vue 计算器应用程序中更新模板变量失败的原因是什么?
【发布时间】:2022-01-05 16:00:38
【问题描述】:

我正在使用 Vue 3 开发一个小型计算器应用程序。在显示部分,我显示算术运算的结果和按下的键的“记录”:

<div class="display">
  <div class="track">
    {{track == '' ? ''  :  track + '=' }}
  </div>
  <div class="result">
    {{currentVal || 0}}
  </div>
</div>

我使用showOperationsTrack(clickedVal) 方法来显示上述“记录”:

const calculatorApp = {
  data() {
    return {
      track: "",
      currentVal: "",
      previousVal: null,
      operation: null,
      isOperatorClicked: false,
      isResultDisplayed: false
    };
  },
  methods: {
    showOperationsTrack(clickedVal) {
      if (!this.isResultDisplayed) {
        this.track = `${this.track}${clickedVal}`;
      } else {
        this.currentVal = "";
      }
    },
    appendClicked(clickedVal) {
      if (this.isOperatorClicked) {
        this.currentVal = "";
        this.isOperatorClicked = false;
      }

      if (this.isResultDisplayed) {
        this.currentVal = "";
        this.isResultDisplayed = false;
      }

      this.currentVal = `${this.currentVal}${clickedVal}`;

      this.showOperationsTrack(clickedVal);
    },
    appendDot() {
      if (this.currentVal.indexOf(".") === -1) {
        this.appendClicked(".");
      }
    },
    setPreviousVal() {
      this.previousVal = this.currentVal;
      this.isOperatorClicked = true;
    },
    add(clickedVal) {
      this.operation = (a, b) => a + b;
      this.setPreviousVal();
      this.showOperationsTrack(clickedVal);
    },
    subtract(clickedVal) {
      this.operation = (a, b) => a - b;
      this.setPreviousVal();
      this.showOperationsTrack(clickedVal);
    },
    multiply(clickedVal) {
      this.operation = (a, b) => a * b;
      this.setPreviousVal();
      this.showOperationsTrack(clickedVal);
    },
    divide(clickedVal) {
      this.operation = (a, b) => a / b;
      this.setPreviousVal();
      this.showOperationsTrack(clickedVal);
    },
    equals() {
      this.currentVal = this.operation(
        parseFloat(this.previousVal),
        parseFloat(this.currentVal)
      );
      this.isResultDisplayed = true;
      this.previousVal = null;
    },
    clearDisplay() {
      this.currentVal = "";
      this.track = "";
    }
  }
};
Vue.createApp(calculatorApp).mount("#myCalculator");
body {
  padding: 0;
  margin: 0;
}

body * {
  box-sizing: border-box;
}

.container {
  min-height: 100vh;
}

.calculator {
  font-family: Montserrat, sans-serif;
  width: 100%;
  max-width: 360px;
  min-width: 300px;
  margin: 10px auto;
  padding: 36px;
  background: #efefef;
  border-radius: 10px;
}

.display {
  position: relative;
  font-weight: bold;
  display: flex;
  flex-direction: column;
  background: #c3c3c3;
  border-radius: 10px;
  margin-bottom: 34px;
  padding: 10px 20px;
}

.result,
.track {
  display: flex;
  justify-content: flex-end;
}

.result {
  margin-top: 3px;
  font-size: 48px;
}

.track {
  position: absolute;
  top: 5px;
  left: 20px;
  right: 20px;
  font-size: 12px;
}

.buttons-container ol {
  list-style-type: none;
  padding: 0;
  margin: 0;
  color: #242424;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  column-gap: 10px;
  row-gap: 10px;
}

.buttons-container li,
.buttons-container .clear {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 36px;
  height: 60px;
  font-weight: 600;
  background: #e7e7e7;
  border-radius: 7px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  cursor: pointer;
}

.buttons-container li {
  width: 60px;
}

.buttons-container .clear {
  margin-top: 10px;
  text-transform: uppercase;
  font-weight: 600;
}

.buttons-container .orange {
  background: #ff9800;
  color: #fff;
}

.buttons-container .active {
  transform: translate(1px, -1px);
}
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500,600&display=swap" rel="stylesheet">
<script src="https://unpkg.com/vue@next"></script>

<div class="container">
  <div class="calculator" id="myCalculator">
    <div class="display">
      <div class="track">
        {{track == '' ? ''  :  track + '=' }}
      </div>
      <div class="result">
        {{currentVal || 0}}
      </div>
    </div>
    <div class="buttons-container">
      <ol>
        <li @click="appendClicked('7')">7</li>
        <li @click="appendClicked('8')">8</li>
        <li @click="appendClicked('9')">9</li>
        <li @click="divide('&divide;')">&divide;</li>
        <li @click="appendClicked('4')">4</li>
        <li @click="appendClicked('5')">5</li>
        <li @click="appendClicked('6')">6</li>
        <li @click="multiply('&times;')">&times;</li>
        <li @click="appendClicked('1')">1</li>
        <li @click="appendClicked('2')">2</li>
        <li @click="appendClicked('3')">3</li>
        <li @click="subtract('-')">-</li>
        <li @click="appendClicked('0')">0</li>
        <li @click="appendDot('.')">&middot;</li>
        <li @click="add('+')">+</li>
        <li @click="equals" class="orange">=</li>
      </ol>
      <div @click="clearDisplay" class="clear orange">Clear</div>
    </div>
  </div>
</div>

问题

由于我未能发现的原因,虽然在每次新计算开始时结果正确设置为 0,但操作记录并未设置为 ''

问题

  1. 是什么导致了这个问题?
  2. 什么是可靠的解决方案?

【问题讨论】:

    标签: javascript vue.js vuejs3


    【解决方案1】:

    按下相等时可以清除数据属性track

    const calculatorApp = {
      data() {
        return {
          track: "",
          currentVal: "",
          previousVal: null,
          operation: null,
          isOperatorClicked: false,
          isResultDisplayed: false,
          busy: false
        };
      },
      methods: {
        showOperationsTrack(clickedVal) {
          if (!this.isResultDisplayed) {
            this.track = `${this.track}${clickedVal}`;
          } else {
            this.currentVal = "";
          }
        },
        appendClicked(clickedVal) {
          if(this.busy === true) {
          this.clearDisplay()
          this.busy = false
          }
          if (this.isOperatorClicked) {
            this.currentVal = "";
            this.isOperatorClicked = false;
          }
    
          if (this.isResultDisplayed) {
            this.currentVal = "";
            this.isResultDisplayed = false;
          }
    
          this.currentVal = `${this.currentVal}${clickedVal}`;
    
          this.showOperationsTrack(clickedVal);
        },
        appendDot() {
          if (this.currentVal.indexOf(".") === -1) {
            this.appendClicked(".");
          }
        },
        setPreviousVal() {
          this.previousVal = this.currentVal;
          this.isOperatorClicked = true;
        },
        add(clickedVal) {
          this.operation = (a, b) => a + b;
          this.setPreviousVal();
          this.showOperationsTrack(clickedVal);
        },
        subtract(clickedVal) {
          this.operation = (a, b) => a - b;
          this.setPreviousVal();
          this.showOperationsTrack(clickedVal);
        },
        multiply(clickedVal) {
          this.operation = (a, b) => a * b;
          this.setPreviousVal();
          this.showOperationsTrack(clickedVal);
        },
        divide(clickedVal) {
          this.operation = (a, b) => a / b;
          this.setPreviousVal();
          this.showOperationsTrack(clickedVal);
        },
        equals() {
          this.currentVal = this.operation(
            parseFloat(this.previousVal),
            parseFloat(this.currentVal)
          );
          this.isResultDisplayed = true;
          this.previousVal = null;
          this.busy = true
        },
        clearDisplay() {
          this.currentVal = "";
          this.track = "";
        }
      }
    };
    Vue.createApp(calculatorApp).mount("#myCalculator");
    body {
      padding: 0;
      margin: 0;
    }
    
    body * {
      box-sizing: border-box;
    }
    
    .container {
      min-height: 100vh;
    }
    
    .calculator {
      font-family: Montserrat, sans-serif;
      width: 100%;
      max-width: 360px;
      min-width: 300px;
      margin: 10px auto;
      padding: 36px;
      background: #efefef;
      border-radius: 10px;
    }
    
    .display {
      position: relative;
      font-weight: bold;
      display: flex;
      flex-direction: column;
      background: #c3c3c3;
      border-radius: 10px;
      margin-bottom: 34px;
      padding: 10px 20px;
    }
    
    .result,
    .track {
      display: flex;
      justify-content: flex-end;
    }
    
    .result {
      margin-top: 3px;
      font-size: 48px;
    }
    
    .track {
      position: absolute;
      top: 5px;
      left: 20px;
      right: 20px;
      font-size: 12px;
    }
    
    .buttons-container ol {
      list-style-type: none;
      padding: 0;
      margin: 0;
      color: #242424;
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      column-gap: 10px;
      row-gap: 10px;
    }
    
    .buttons-container li,
    .buttons-container .clear {
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: 36px;
      height: 60px;
      font-weight: 600;
      background: #e7e7e7;
      border-radius: 7px;
      border: 1px solid rgba(0, 0, 0, 0.1);
      cursor: pointer;
    }
    
    .buttons-container li {
      width: 60px;
    }
    
    .buttons-container .clear {
      margin-top: 10px;
      text-transform: uppercase;
      font-weight: 600;
    }
    
    .buttons-container .orange {
      background: #ff9800;
      color: #fff;
    }
    
    .buttons-container .active {
      transform: translate(1px, -1px);
    }
    <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500,600&display=swap" rel="stylesheet">
    <script src="https://unpkg.com/vue@next"></script>
    
    <div class="container">
      <div class="calculator" id="myCalculator">
        <div class="display">
          <div class="track">
            {{track == '' ? ''  :  track + '=' }}
          </div>
          <div class="result">
            {{currentVal || 0}}
          </div>
        </div>
        <div class="buttons-container">
          <ol>
            <li @click="appendClicked('7')">7</li>
            <li @click="appendClicked('8')">8</li>
            <li @click="appendClicked('9')">9</li>
            <li @click="divide('&divide;')">&divide;</li>
            <li @click="appendClicked('4')">4</li>
            <li @click="appendClicked('5')">5</li>
            <li @click="appendClicked('6')">6</li>
            <li @click="multiply('&times;')">&times;</li>
            <li @click="appendClicked('1')">1</li>
            <li @click="appendClicked('2')">2</li>
            <li @click="appendClicked('3')">3</li>
            <li @click="subtract('-')">-</li>
            <li @click="appendClicked('0')">0</li>
            <li @click="appendDot('.')">&middot;</li>
            <li @click="add('+')">+</li>
            <li @click="equals" class="orange">=</li>
          </ol>
          <div @click="clearDisplay" class="clear orange">Clear</div>
        </div>
      </div>
    </div>

    【讨论】:

      猜你喜欢
      • 2022-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-05
      • 2016-09-24
      • 1970-01-01
      • 2011-02-11
      • 1970-01-01
      相关资源
      最近更新 更多