iT邦幫忙

2022 iThome 鐵人賽

DAY 13
0
Modern Web

不用去柬埔寨也能活摘 Vue系列 第 13

[Vue] Day13 methods及computed 的資料整合與邏輯運算

  • 分享至 

  • xImage
  •  

在上篇文章中,有與各位分享到 Vue 的語法,以及如何將實體 data 結合運算式並渲染至畫面。那如果遇上複雜的運算邏輯時,或是重複置入同樣的複雜運算式時,模板會變得難以維護。假設我們需要在不同的網頁中呈現「班級人數」時,就會在每個頁面中寫上相同的程式碼,那就可能讓我們在維護上增加遺忘的機率,而且在模板中插入了過於複雜的邏輯運算時,不僅造成程式碼混亂難以維護,也可能發生不可預期的危險。

那以下,我們就來和各位聊聊,該如何解決此問題吧!

methods (方法)

當我們在開發專案時,有時會遇到明明同樣的東西,但我們卻寫了3次、4次、5次...甚至更多。這樣不僅讓我們花費更多時間,也導致在日後的維護上會更加的困難,這時候呢,我們就只需要將重複的部分提取出來並包裝成函式以便重複使用,必且放在 methods的屬性中。

<script>
export default {
  data() {
    return {
      price: 500,
      people: 3,
    };
  },
  methods: {
    iThome_2022() {
      return this.price * this.people;
    },
  },
};
</script>

而在 methods 中,是需要使用 this 去存取 data 裡的屬性,並且在 HTML 中使用 methods 時需要加上小括號,或設計成帶有參數的方式去執行。

照上方的範例程式碼來看,我們已經將邏輯完成了,那接下來如果想讓他在網頁上呈現呢?就可以在模板裡,透過去呼叫 iThome_2022() 的方式去獲取我們要的金額 (price * people)

<template>
  <div>
    <p>價格:{{ price }}</p>
    <p>人數:{{ people }}</p>
    <p>金額為 {{ iThome_2022() }} 元</p>
  </div>
</template>

網頁呈現結果:

那需要特別注意的是,在 Vue 的實體中,我們可以透過 this 來存取我們想要的實體。舉個例子,我們看回上方的範例程式碼,price 和 people 已經被我們放在 data 裡面了,但到了 methods 時,我們就需要在他們的前面加上 this 後才能存取他們。

值得一提的是,在 methods 裡面的內容其實是一個 function,在我們需要使用時就可以呼叫他,所以在 <template> 中就需在他們的兩側加上小括號,就像這樣:iThome_2022(),當然有必要時我們也可以加上參數傳過去。

除此之外,各位也需要注意一點,如果我們想在 Vue 實體中的另一個 methods 呼叫 iThome_2022() 時,就需要在前面加上 this,那如果是想在 <template> 中呼叫就不需要囉!

Computed

Computed 與 methods 的寫法可說是一模一樣的,讓我們看看範例:

<script>
export default {
  data() {
    return {
      price: 500,
      people: 3,
    };
  },
  computed: {
    iThome_2022() {
      return this.price * this.people;
    },
  },
};
</script>
<template>
  <div>
    <p>價格:{{ price }}</p>
    <p>人數:{{ people }}</p>
    <p>金額為 {{ iThome_2022 }} 元</p>
  </div>
</template>

可以看得出來不一樣的地方只有 data 後面的 methods 與 computed,與 html 中少了小括號,但要注意的是,雖然差不多,但兩者的功能終究還是不同的,所以可不能相互改寫喔!讓我們把他們寫在一起看看:

<script>
export default {
  data() {
    return {
      price: 500,
      people: 3,
    };
  },
  computed: {
    iThome_2022_computed() {
      console.log("computed");
      return this.price * this.people;
    },
  },
  methods: {
    iThome_2022_methods() {
      console.log("methods");
      return this.price * this.people;
    },
  },
};
</script>
<template>
  <div>
    <p>價格:{{ price }}</p>
    <p>人數:{{ people }}</p>
    <p>金額為 {{ iThome_2022_computed }} 元</p>
    <p>金額為 {{ iThome_2022_methods() }} 元</p>
  </div>
</template>

寫完程式碼後,讓我們看看網頁的輸出結果:

那這時,如果我們將 <template> 裡稍作修改,將他們重複各寫兩次:

<template>
  <div>
    <p>價格:{{ price }}</p>
    <p>人數:{{ people }}</p>
    <hr />
    <p>金額為 {{ iThome_2022_computed }} 元 (computed)</p>
    <p>金額為 {{ iThome_2022_computed }} 元 (computed)</p>
    <p>金額為 {{ iThome_2022_computed }} 元 (computed)</p>
    <hr />
    <p>金額為 {{ iThome_2022_methods() }} 元 (methods)</p>
    <p>金額為 {{ iThome_2022_methods() }} 元 (methods)</p>
    <p>金額為 {{ iThome_2022_methods() }} 元 (methods)</p>
  </div>
</template>


可以看見網頁上所呈現的 computed 與 methods 都是各三行

那由於我們在上方兩個函式裡都寫了 console.log(),就來看看主控台 console :

可以看到 methods 的前面多了一個 3,代表iThome_2022_methods() 執行了三次。
而 computed 前面沒有數字,代表 subtotalComputed 只執行了一次。

這是為什麼呢?
因為 computed 的屬性是會將計算過後的結果暫存,後續如果也沒有更新的話,computed 也就不會重複執行。如果同樣都是重複計算的話,使用 computed 來處理會比 methods 來得好,但要特別注意的是,computed 的 function 是無法使用參數的,若有需要帶入參數的情況時,建議用 mehtods 來處理會比較好喔!

Methods 與 Computed 差異

  • computed
    1.計算後會將結果暫存。
    2.如果暫存後的資料後續沒有變動,就不會重複執行。
    3.擅長執行重複計算,可節省較多效能。
    4.無法帶入參數。

  • Methods
    1.如是在 HTML 裡被使用多次,就會執行多次。
    2.可帶入參數。

Methods 與 Computed 小小實作

最後,就讓我們來做一個小實作結束這回合吧。

相信各位再求學階段時,都有量過身高體重吧,但在算 BMI 時,甚麼平方算完再除,是不是很麻煩呢,那就讓我們來做一個簡易的 BMI 計算機吧:

首先,我們再網頁中放入兩個 input 輸入框及一個 button:

<template>
  <div>
    <p>BMI 算法:體重除以身高的平方<br /></p>
    <div>身高 <input type="text" /> 公分</div>
    <div>體重 <input type="text" /> 公斤</div>
  </div>
  <button style="margin: 15px">開始計算</button>
  <br />
  <input type="text" readonly />
</template>

可以看到以上程式碼,我們將身高體重的 input 的 type 設定成 "text",讓使用者可以輸入自己的身高和體重,輸入後便可按下開始計算的 button,計算的結果就會呈現在我們的 input 裡,那為甚麼我們要在這邊用上 input 呢?其實是因為可以方便我們直接加上 v-model 去計算數值,readonly則是設定成唯讀。

不懂 v-model 沒關係,後續會專門寫一篇做介紹,簡單來說就是讓我們的資料可以雙向綁定,計算完後直接呈現在上面,而目前可以用 v-model 的只有 input、select、checkbox

再看看我們的網頁:

那只有網頁沒有功能也不行,所以接下來我們來做功能部分:

首先,我們需要先在 button 的部分加入事件綁定:@click(有關事件綁定:v-on 後續也會與各位做介紹),讓我們點擊按鈕後就可進行函式的運算

<button style="margin: 15px" @click="BMI()">開始計算</button>

那計算後要如何抓取使用者輸入的值呢,就需要用到v-model了:

<div>身高 <input type="text" v-model="height" /> 公分</div>
<div>體重 <input type="text" v-model="weight" /> 公斤</div>

像這樣,就可以在使用者輸入身高和體重後,將數值暫存

接下來就進行運算,bmi 的算法是體重(公斤)除以身高(公尺)的平方,轉換成程式語言後就是:
weight / (height*height)

也因台灣人常用的身高單位是公分,但 bmi 的身高單位是公尺,所以改寫一下:
weight / ((height / 100 )*(height / 100))
(1公尺 = 100公分)

我們也為了避免計算過後的小數點太長,所以只取他的小數點後3位就好:
(weight / ((height / 100 )*(height / 100))).toFixed(3)
(toFixed:四捨五入,括號裡輸入想取到小數點第幾位)

最後,我們可以透過 parseFloat 來解析數值:
parseFloat((weight / ((height / 100 )*(height / 100)))).toFixed(3)

ok,計算完成了,但要顯示在哪裡呢?就是我們的唯讀 input 對吧,那這時候又需要呼叫 v-model 了,v-model 是用來資料雙向綁定的,那除了可以抓取使用者輸入的值,當然也能把計算後的值馬上呈現在網頁拉,就像這樣:

<input type="text" v-model="bmiValue" readonly />

再來我們要進入 <script> 的環節拉了

首先,先在 data 中宣告 bmiValue 的屬性,讓我們可以在 button 點擊後馬上呈現:

data() {
  return {
    bmiValue: "",   
  };
},

運算將他寫在 methods裡,這邊要先跟各位說明一下我們設計程式的邏輯:
當使用者輸入身高及體重後,點擊開始計算的按鈕,結果即會呈現在 input 的欄位

所以,我們的運算式就會寫在 BMI() 這個函式裡,並讓計算出的結果輸出到 bmiValue中,而 input 的v-model 則會幫助我們將計算結果呈現於網頁上:

methods: {
    BMI() {
      this.bmiValue = Number.parseFloat(
        Number(this.weight) /
          Number(Number(this.height / 100) * Number(this.height / 100))
      ).toFixed(3);
    },
  },

就像這樣,那需要注意的是,為了去解析數值,我們在有計算的部分都要加上一個 Number,且為了讓 Vue 知道我們想要指定 html 的 v-model ,所以在呼叫時需要在前面加上 this

最後來看看我們的網頁:

恭喜各位,那我們的 bmi 計算器的小小實做就成功拉。

bmi 計算器完整程式碼

<template>
  <div>
    <p>BMI 算法:體重除以身高的平方<br /></p>
    <div>身高 <input type="text" v-model="height" /> 公分</div>
    <div>體重 <input type="text" v-model="weight" /> 公斤</div>
  </div>
  <button style="margin: 15px" @click="BMI()">開始計算</button>
  <br />
  <input type="text" v-model="bmiValue" readonly />
</template>

<script>
export default {
  data() {
    return {
      bmiValue: "",
    };
  },
  methods: {
    BMI() {
      this.bmiValue = Number.parseFloat(
        Number(this.weight) /
          Number(Number(this.height / 100) * Number(this.height / 100))
      ).toFixed(3);
    },
  },
};
</script>

那我們今天對於 methods 及 computed 的介紹就到這裡結束拉
希望今天實作的講解是淺顯易懂的,讓看過的人都可以學會!謝謝大家<3
/images/emoticon/emoticon42.gif


上一篇
[Vue] Day12 起手式:Composition API
下一篇
[Vue] Day14 資料綁定:v-bind、v-model
系列文
不用去柬埔寨也能活摘 Vue30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言