Vue options api

tags: vue筆記

methods 方法

methods觸發

methods 的觸發方法有很多種:

  1. 一般指令:click,change像是下方範例。

    ​​​​<button type="button" @click="trigger('Click Methods')">點擊觸發</button>
    
  2. 其它 options api,意思是其他 methods 互相呼叫。

    ​​​​<button type="button" @click="callOtherMethod">呼叫另一個 methods</button>
    

    以這個範例是,上面的按鈕先觸發一個 function ,再由該 function 觸發另外一個 function

    ​​​​methods: {
    ​​​​    trigger(name) {
    ​​​​      console.log(name, '此事件被觸發了')
    ​​​​    },
    ​​​​    callOtherMethod() {
    ​​​​      this.trigger('由 callOtherMethod 觸發')
    ​​​​    },
    ​​​​  },
    
  3. 生命週期觸發:created,mounted,這就是Vue本身的生命步驟了,當到了該步驟就會觸發。

    ​​​​created() {
    ​​​​    this.trigger('由生命週期觸發');
    ​​​​  },
    

注意:

撰寫 options api 的函式,不要使用箭頭函式,因為 options api 大量使用 this,使用箭頭函式會無法取得 this 資料!

Dom事件傳參數

在寫普通Js時,經常用到 e.target 等,在 Vue 要用這個時,要在該Dom事件中傳入 $event 參數。

<button type="button" @click="methodParameter($event)">參數傳入</button>

這樣在該函式就可以收到Dom事件相關資料,也就可以取得像是dataset等資料。

methodParameter(e) {
  console.log(e.target.dateset)
},

搭配 v-for 傳入參數

搭配v-for是非常常用的作法,其實跟原生 js 搭配 data- 屬性的概念有點相似,以下就用範例說明:

<template v-for="product in products" :key="product.id">
  <div @click="openProductDetail(product)">
    <p>{{product.title}}</p>
    <p>{{product.origin_price}}<p>
  </div>
</template>

v-for="product in products" 前面的 product 就是自定義的每一筆陣列資料,只要把該值當作參數帶入即可做後續操作,像是 push 或是 篩選 等等。


computed運算

computed 跟其他幾個 method 不同,其他可以直接操作,但是 computed 大部分是讀取資料,計算新的結果再回到畫面上。雖然說是這樣說,但是大部分感覺跟 methods 有點像,不一樣的是裡面會是 return,而這個 return 值就可以直接用來呈現在畫面中:

const App = {
  computed:{
    total(){
      let num = 0;
      this.cart.forEach((item)=>{
          num += item.price
      })  
      return num;
    }
  }
};

常見的購物車計算總值,計算後可以當作他是一般data一樣。

{{total}}

*一定要 return 東西,否則會出錯。
*另外要注意說 computed 只要裡面資料更新,就會調用並回傳,所以當this.carts 中新增資料,該函式自動會更新。

search 是常見的網頁功能,所以一定要學會!而使用 computed 可以輕鬆達成,首先給input先綁定一個v-model="search" 字串資料,我們的做法就是當搜尋時,把符合需求的值送進 filterProducts 陣列,然後下面的 v-for 會呈現 filterProducts 陣列的值:

<input type="search" v-model="search">
  <ul>
    <li v-for="item in filterProducts">
      {{ item.name }} / {{ item.price }}
    </li>
  </ul>

所以在 computed 寫一個 filterProducts() ,塞選出 item 的 name 屬性 match 搜尋的值:

const App = {
  computed:{
    filterProducts(){
      return this.products.filter(item=>{
        return item.name.match(this.search);
      })
    }
  }
};

computed 運算之Getter,Setter

computed 把 data 中資料取出放到函式運算後取去渲染畫面,這叫做 Getter 。

computed 還有另外一個 setter ,是把資料重新調整後送回 data 中。

如果要加入 Getter 和 Setter ,需要把 computed 修改成物件形式:

const App = {
	computed:{
		total:{
			get(){
				let total = 0;
				this.carts.forEach(item=>{
					total += item.price
				})
				return total
			}	
		}
	}
};

改成上面這樣 get() ,依舊可以運作,這時候我們可以新增一個 input ,嘗試操作該函式中的total值 @click="total = num"

<input type="number" v-model.number="num">
<button type="button" @click="total = num">更新</button>
total 的值:{{ total }}
sum 的值:{{ sum }}

這時候其實不會有任何動作,因為computed一開始只有讀取功能,我們可以來寫 set() ,但要記得 set(參數),要帶入一個參數:

const App = {
  computed:{
    total:{
      get(){
        let total = 0;
        this.carts.forEach(item=>{
          total += item.price
        })
        return this.sum || total
        },
      set(val){
        this.sum = val * 0.8
      }
    }
  }
};

另外可以看到 get() 中,return this.sum || total 改變了,是因為可以設定如果有 set 產生新值,就用新值,不然用舊值。


Watch監聽

watch 跟 computed 有點像, computed 是把 data 值取出重新運算在渲染,而 watch 是 監聽單一data 值,而該值有變化,就會觸發事件。

*注意 watch 不會產生新值,而是修改 data 內容,而 data 有變化自然畫面也會跟著變化。

以下範例是當 input 值變化,就會呼叫 watch 透過 calMoney() 去判定並改變 data 中的 result:

<input type="number" id="name" v-model.number="money">
<P>result: {{ result }}</P>

watch 物件中把要監聽的變數名稱建立成函式,而函式帶入兩個參數,第一個是改變後的新值,第二個是上一次變化的舊值,記得只要值改變,就一定會呼叫:

const App = {
  data() {
    return {
      money:0,
      result: '',
    }
  },
  watch:{
    calMoney( newValue , oldValue ){
     if(newValue > 10){
       this.result = `數字大於10`
     }else if(newValue < 10){
       this.result = `數字小於10`
     }
    },
  },
};

與computed有什麼不同?

  • watch:只能監聽一個值,但是能在函式中同時操作很多data資料。如果需要監聽多個值,就要重複寫很多個函式。
    而且watch一開始打開頁面不會執行任何動作,因為本身資料沒有改變。

  • conputed:一次監聽data多筆資料,但是只會 return 出一個值,所以產出的結果就是那個值。

watch 深層監聽

前面 watch 監聽的都是一個單一值,watch也能監聽物件,但是要改成深層監聽的方式

<label for="productName">商品名稱</label>
<input type="text" v-model="product.name">
<label for="productPrice">商品價格</label>
<input type="number" v-model.number="product.price">
<label><input type="checkbox"  v-model="product.vegan"> 素食</label>
<p>result : {{ result }}</p>

上面範例是input各自配對到物件的每個屬性,改變該值自然就改變了物件。

const App = {
  data() {
    return {
      product: {
        name: '蛋餅',
        price: 30,
        vegan: false
      },
      result: '',
		}
  },
  watch:{
    product:{
      deep:true,
      handler(newValue , oldValue){
        this.result = `總共買了${this.product.name},花了${this.product.price}`
      }
    }
  },
};

這裡的 product 要改成物件寫法,同時裡面要加上 deep:true 的屬性值,最後加上一個控制器handler(newValue , oldValue) ,控制器函式就跟原本的 watch 差不多了,這時候兩個參數newValue , oldValue,分別代表的是新舊product物件,那就能用該值做事情摟~


Vue的元件命週期

一個網頁有很多Vue子元件,包含像是header,sideNav,main等等,當切換頁面時自然就會讓有些元件卸載再重新生成,那就會觸發不同生命週期。

  • beforeCreat:資料建立前

  • created:資料已經建立完成

  • beforeMount:準備把 HTML 結構掛載到畫面上,但還沒掛載上去。

  • mounted:已經把 HTML 結構掛載上去,通常到這裡代表畫面已經完成,所以會停在這裡,除非有任何資料變更,那才會進到下一步。

*如果需要針對生成的HTML做操作,JS要下在 mounted 之後,因為在mounted 之前HTML還沒生成。

  • beforeUpdate、updated:很清楚就是更新資料前後。

  • beforeUnmount、unmounted:最後卸載前和卸載後的狀況,在這兩個階段其實都還能抓到資料喔。


v-if 和 v-show

v-if 是判定是否存在,所以只要關閉再啟動,就會重新抓取資料,如果資料變更後沒做存取,那資料會被重置。

v-show是判定用 display:none 是否顯示,所以資料還在,只是隱形了。

但一般常會使用 v-if 來做開發,較能正確使用生命週期,這時候如果要保留資料狀態,就要使用 keep-alive 標籤 ,只要在外層包上 keep-alive

<keep-alive>
  <child v-if="isShowing"></child>
</keep-alive>

當關閉 v-if 時,生命週期會進入 deactivated() ,而再次啟動時,會進入 activated() 同時上次變更的資料狀態還會保留著。