Vue 組件編寫:簡易計算器


話不多說,碼上開始。


建立項目

  1. 首先下載 安裝 Node.js 環境,它會自動安裝 npm 包管理工具。在使用之前我們修改一下 npm 包的下載路徑,不然放在 C 盤怎么得了?在命令行中輸入 npm config ls 可以看到 prefix 的值就是下載路徑,輸入 npm config set prefix "你的路徑" 就可以修改。
  2. 安裝 vue-cli 腳手架工具npm install -g vue-cli,參數 -g 表示全局安裝(路徑在之前設置的 prefix 中),否則就是本地安裝(路徑在當前目錄)。
  3. 建立項目,在某目錄下,輸入 vue init webpack-simple 項目名稱,參數 webpack-simple 是一個項目模板;按提示輸入相關信息后,將自動新建項目文件夾,輸入 cd 文件夾名稱 進入目錄,輸入 npm install,在當前項目路徑下載所需的包;輸入 npm run dev 就可運行了。 dev 是 package.json里面定義的腳本命令,作用是啟動服務器。

打開 Vue.app 文件,我們就可以在里面愉快的寫組件了。
這里不再介紹 Vue 的基本知識,若要學習請移步 Vue2.x 教程


需求分析

其實文章開頭說的 話不多說,碼上開始 是一種十分錯誤的做法。我就是在想當然之后——按照腦海中最初浮現的邏輯——馬上開始寫界面,吭哧吭哧地開始寫事件處理程序。隨后,在測試中痛苦地發現,功能太簡陋,簡單的單次計算並不能滿足我們印象中對於計算器的期待。

好吧,推倒重來,如果上天再給我一次機會,我會好好地做需求分析……

首先,我們打開一個計算器看看它有什么功能:

也就是說,計算器應該支持單次運算、連續計算、繼續計算,遵循運算符的優先級順序,並具有一定的容錯機制。

幾經修改,最后整理流程圖如下:


組件結構

  • 首先,為了進行四則運算,我們需要一個操作符棧 oprStack 和一個數值棧 numStack
  • 為了顯示算式的功能,我們需要一個數組 cacheArr 順序記錄輸入和操作符和數值。
  • 由於顯示部分應該綁定一個字符串變量 cacheStr,此變量又於上述數組相關,那么為了保持數據結構的簡單,對於這個字符串變量,我們使用計算屬性。
  • 一些緩存變量,inputData preType
  • 一些標志變量,calculated inputShow errorOccurred

那么自然而然地,計算器組件的結構設計如下:

<template>
  <div id="calculator">
    ...
    <div id="panel">
      <hr>
      <div>{{ cacheStr }}</div>
      <hr>
      <div :class="{'text-danger' : errorOccurred}">{{ inputData }}</div>
      <hr>
    </div>
    <div id="board" @click="changePanel($event);inputHandler($event)">
      <table>
      ...
      </table>
    </div>
  </div>
</template>
<script>
  export default{
      data () {
          return{
              cacheArr:[], //顯示算式
              inputData:'', //緩存輸入數值
              preType:'num', //上一個輸入類型
              oprStack:[], //操作符棧
              numStack:[], //操作數棧
              calculated:0, //連續計算和重新計算等邏輯需要的標志
              inputShow: 0, //inputData 有時作為輸入有時作為輸出,需要一個標志
              errorOccurred: 0 //錯誤標志

          }
      },
      computed:{
          cacheStr() {
              ...
              return this.cacheArr.join("");
          }
      },
      methods: {
          /** 初始化 */
          init(){
              ...
          },

          /** 顯示處理 */
          changePanel(e){
			...
          },

          /** 輸入處理 */
          inputHandler (e) {
              ...

              //重新計算判斷:1. 上次計算后輸入 num 或 opr0; 2. 上次計算結果是 NaN;
              if(...){
                  this.init();
              }

              //繼續計算判斷:1. 上次計算后輸入 opr1 或 opr2
              if(...){
                  //主要處理顯示的部分
                  ...
              }

              // inputData 從顯示模式調整為輸入模式
              ...

              //處理數字-----------------------------------------
              if(type === 'num'){
                  ...
              }

              //處理管理級操作符---------------------------------
              if(type==='opr0'){
                  ...

              }

              //處理其他操作符----------------------------------
              if(type==='opr1' || type==='opr2'){
                  //查看寄存器是否有數據
                  ...

                  //容錯機制
                  //1. 如果輸入二元操作符-等號,則刪掉二元操作符
                  //2. 如果連續輸入兩次二元操作符,則刪掉前一個
                  ...

                  //處理
                  if(value==='equals')
                  {
                      this.oprStack.push({type:type, value:value, level:level});
                      this.preCalculate();
                      this.calculated = 1;
                  }
                  else{
                      this.oprStack.push({type:type, value:value, level:level});
                      this.calculated = 0;
                  }

              }

              //保存等號前的最后一個輸入類型--------------------
              ...

          },

          /** 計算預處理 */
          preCalculate () {

              //計算
              this.calculate(this.oprStack, this.numStack);

              //顯示結果數據
              ...
          },

          /** 計算過程 */
          calculate(oprStack, numStack){
              //對操作符棧和數值棧進行計算,考慮四則運算的優先級
              ...
          },

          /** 具體計算函數 */
          ...
      }

  }
</script>
<style>
 ...
</style>


大體思路就是這樣,一個計算器應該保持簡單、直觀的使用方式,以免造成用戶的困惑。

比如說,自帶的計算器里面,上一次計算結果既在顯示屏上,也在數值棧中,當用戶進行“繼續計算”時,輸入一個二元運算符,緊接着輸入一個等號,計算器會把當前顯示屏的數值當做第二個操作數,但這可能不是用戶想要的,因為他並沒有輸入第二個操作數。

在 po主的計算器中,把最后一個輸入是二元運算符這種情況當作誤操作,自動去掉,以免造成混淆。


##踩坑小記 這是一點題外話,主要是記錄一下自己犯的錯誤,大佬們請忽略~ 1. Unicode 字符值的使用。可以到 [Unicode 官網](http://www.unicode.org/charts/) 上查詢字符值(16進制),比如說 ÷ 號:00f7。
在 JavaScript 中使用:`\u00f7`,在 CSS 中使用:`\00f7`,在 html 中使用:`&井號247;`。注意 html 中是10進制噢!這里 po主為了避免 markdown 語法自動轉換成除號把 ‘#’ 改成了 ‘井號’,各位童鞋自行轉換哈… 2. Vue 文件的 debug 方法。我們知道,使用了 webpack 的項目中,腳本最后要經過編譯、壓縮、打包,在瀏覽器的調試工具中是無法調試的。
一開始我采用的方法是,在源代碼要斷點的地方輸入 `debugger`,在運行時就可以進入調試模式了。
后來經老大介紹,有一個叫 Vue DevTools 的工具,各位童鞋可以網上自取。 3. 跟常識相悖的是:空對象 `{}` 竟然是真值。所以判斷空對象時 `if(!nullObj){...}` 並不會得到你想要的結果。可以使用 jQuery 中的判斷空對象方法: ```javascript function isEmptyObject(e) { var t; for (t in e) return !1; return !0 } ``` 4. 由於存在 NaN 這個神奇的毒瘤,以及 Infinity 這樣的值,所以判斷一個變量是否數值的方法: ```javascript function isNumber(value){ return typeof value === 'number' && isFinite(value); } ``` 5. 在 Vue 中,可以在你的方法中訪問計算屬性,但不要試圖去更改它,因為沒用。在下次使用該計算屬性時,它依然會調用自身的方法來計算。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM