---
# System prepended metadata

title: vue watch computed v-on 7
tags: [vue]

---

# vue watch computed v-on 7

###### tags: `vue`
基本概念
這次我們來說明watch、computed、v-on的用法，
watch有點像是監聽的概念，當監聽的值或物件有變動時，就會觸發watch裡的程式。
computed和watch有點像，但他不能抓修改前後的值，有緩存機制，相依data，主要用來減少template裡的邏輯運算。
v-on也算是監聽，簡寫為@。

---
### 實作
#### watch
先來做簡單的監聽data，先新增一個data叫test，再新增一個input，v-model test。
![](https://i.imgur.com/jJ4YmP9.jpg)
我們在script裡打上
![](https://i.imgur.com/7R6oY19.jpg)
test表示監聽名稱為test的data，裡面有包immediate和handler，handler表示當監聽的東西改變時就會執行裡面的程式碼，immediate表示是否在剛載入時就執行一次。
我們還可以在handler傳入兩個值。
![](https://i.imgur.com/HcagfUq.jpg)
af是修改後的值，be是修改之前的值，有了這兩個值就可以拿來做更進一步的運算。
如果我們想要讓handler寫成function的方式可以改寫成這樣。
![](https://i.imgur.com/TwVias3.jpg)

![](https://i.imgur.com/WoA1Wan.jpg)
在handler裡打function名稱，在methods裡做處理。

如果你要監聽的東西是物件型態的話，要改成
![](https://i.imgur.com/BRc07ss.jpg)

![](https://i.imgur.com/z24079w.jpg)
把監聽的物件改成字串的方式就可以監聽了

程式碼

```
<template>
  <div class="home">

   <input type="text" v-model="obj.a">
   <br>
    <p>之前:{{oldvalue}}</p>
    <br>
    <p>現在:{{newvalue}}</p>

  </div>

</template>

<script>
// @ is an alias to /src
/*eslint-disable*/
export default {
  name: 'watch',
  components: {
  },
    data:()=>({
        dd:5,
        obj:{
            a:42,
            b:55
        },
        test:"asd",
        newvalue:"",
        oldvalue:""

    }),
     watch:{
         test:{
            immediate:false,
            handler(af,be){
                this.newvalue = af
                this.oldvalue = be
                console.log("change")
            }
            },
     
         dd:{
            handler:"ddhandle",
            immediate:false
            },
     
         "obj.a":{
             immediate:false,
             handler(af,be){
                 this.newvalue = af
                 this.oldvalue = be
                 console.log("change")
             }
         },
    
     },
     methods:{
         ddhandle(af,be){
            this.newvalue = af
            this.oldvalue = be
             console.log(be+"   change   "+af);
         }
    },
}
</script>

```

---
#### computed
```
<template>
  <div class="home">
   <input type="text" v-model="gg">
   <p>{{reversegg}}</p>
  </div>
</template>
<script>
// @ is an alias to /src
/*eslint-disable*/
export default {
  name: 'watch',
  components: {
  },
    data:()=>({
      gg:"i am student"
    }),
     computed:{
        reversegg() {
            return this.gg.split('').reverse().join('');
        },
     },
}
</script>

```
新增一個data叫gg，在computed裡打要做計算的值。

computed主要是做data資料的計算(因為data無法計算或放判斷式)，一般我們要反轉字串都會直接在template做反轉，有了computed就可以讓程式碼更易讀。


---

#### v-on

大部分的html標籤都可以放@，基本樣式為
```
@事件="內容"

範例:
<button class="btn btn-dark" @click="dd+=1">dark</button>
```

事件為觸發內容的方式有click、change、mouseover等...
達成事件後就會執行內容

v-on還可以做其他修飾
我們先做3個div
![](https://i.imgur.com/MLmtskH.jpg)
程式碼
![](https://i.imgur.com/TSMkp4A.jpg)
我們發現了一個問題，當我點了綠色div會觸發a、b、c三個function
那我要怎阻止這個問題?


---

把程式碼改成
```
    <div id="a" @click.self="a()">
      <div id="b" @click.self="b()">
        <div id="c" @click.self="c()">
        </div>
      </div>
    </div>
```
.self 只會點擊本元素才會執行，並不會由其他元素間接執行


---

也可以改成
```
    <div id="a" @click="a()">
      <div id="b" @click.stop="b()">
        <div id="c" @click.stop="c()">
        </div>
      </div>
    </div>
```
.stop 會在觸發後阻止點擊事件向父元素傳遞


---

當然還有其他修飾字符
.capture 一般我們點擊最小的div時會由子到父觸發function，有了capture我們點擊最小的div會由父到子觸發function
```
<div id="a" @click.capture="a()">
      <div id="b" @click.capture="b()">
        <div id="c" @click.capture="c()">
        </div>
      </div>
    </div>
```


---
.once 很簡單，就是只會觸發一次
```
<div id="a" @click.once="a()">
      <div id="b" @click.once="b()">
        <div id="c" @click.once="c()">
        </div>
      </div>
    </div>
```