Vue計算屬性與偵聽器和過濾器超詳細介紹

1. 計算屬性

1.1 使用方法

概述:

模板中放入太多的邏輯會讓模板過重且難以維護,使用計算屬性可以讓模板變得簡潔易於維護。計算屬性是基於它們的響應式依賴進行緩存的,計算屬性比較適合對多個變量或者對象進行處理後返回一個結果值,也就是數多個變量中的某一個值發生瞭變化則我們監控的這個值也就會發生變化。

計算屬性定義在Vue對象中,通過關鍵詞computed屬性對象中定義一個個函數,並返回一個值,使用計算屬性時和data中的數據使用方式一致。

使用:

當不使用計算屬性時,我們想要計算模板中的結果,可以有下面幾種寫法:

<div id="app">
    <!-- 方法1:vue在使用時,不推薦在模板中來寫過多的邏輯 -->
    <h3>{{ n1+n2 }}</h3>
    <!-- 方法2:對於一個計算結果,可能在當前的頁面中,顯示多個,顯示幾次就調用這個函數幾次,性能會降低 -->
    <h3>{{ sum() }}</h3>
    <h3>{{ sum() }}</h3>
    <h3>{{ sum() }}</h3>
</div>
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            n1: 1,
            n2: 2
        },
        methods: {
            sum() {
                console.log('sum --- methods');
                return this.n1 + this.n2
            }
        }
    })
</script>

在這裡插入圖片描述

如果對於一個結果,進行計算,可以使用vue提供計算屬性來完成,而且計算屬性它還具有緩存功能。如果你的依賴項,沒有發生改變,則它會在再一次調用時,會讀取緩存中的數據。

<div id="app">
    <div>{{total}}</div>
    <div>{{total}}</div>
    <div>{{total}}</div>
</div>
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            n1: 1,
            n2: 2
        },
        // 計算[屬性]
        computed: {
            // 調用時,直接寫名稱就可以,不用寫小括號
            // 計算屬性中的依賴項,可以是一個,也是可以N個,取決於你在計算屬性中調用多少
            // 註:此方法中不能寫異步
            // 簡寫 使用最多的寫法
            total() {
                console.log('computed -- total')
                // 在計算屬性中,調用瞭 n1和n2,則n1和n2就是它的依賴項,如果這兩個依賴項,有一個發生改變,則它會重新計算,如果兩個都沒有發生改變,則第2之後調用,讀取緩存中的數據
                return this.n1 + this.n2
            }
        },
        methods: {
            // 計算屬性中的方法在 methods 中也可以調用
            sum() {
                console.log('sum --- methods', this.total);
                return this.n1 + this.n2
            }
        }
    })
</script>

在這裡插入圖片描述

註意:

  • 計算屬性在調用時,在模板中直接寫名稱就可以,不用寫小括號。
  • 在計算屬性中,調用瞭 n1和n2,則n1和n2就是它的依賴項,如果這兩個依賴項,有一個發生改變,則它會重新計算,如果兩個都沒有發生改變,則第2之後調用,讀取緩存中的數據。這也就是為什麼上面計算瞭3次,卻隻調用瞭一次計算方法,因為計算屬性中的依賴項沒有發生改變。
  • 計算屬性中的依賴項,可以是一個,也是可以N個,取決於你在計算屬性中調用多少。
  • 計算屬性中的方法中不能寫異步。
  • 上面計算屬性,是簡寫。簡寫是使用最多的方法。
  • 計算屬性不僅可以在模板中調用,也可以在 method 中調用。

如果定義的計算屬性,為簡寫方式,則給計算屬性賦值時,會報錯。隻有標準的寫法時,它才可以對於計算屬性進行賦值操作。下面我們就來看一下標準寫法是怎樣的。

<div id="app">
    <h3>{{ sum() }}</h3>
    <h3>{{msg}}</h3>
</div>
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            n1: 1,
            n2: 2,
            msg: ''
        },
        // 計算[屬性]
        computed: {
            // 標準寫法
            total: {
                // 簡寫隻是實現的瞭標準寫法中的get方法
                get() {
                    return this.n1 + this.n2
                },
                set(newVal) {
                    if (newVal > 10) {
                        this.msg = '值有點的大'
                    }
                }
            }
        },
        methods: {
            sum() {
                // 賦值隻會觸發標準方式中的set方法,然後你可以得到它,完成一些別的工作
                if (this.total > 6) {
                    this.total = 101
                }
                return this.n1 + this.n2
            }
        }
    })
</script>

在這裡插入圖片描述

註意:

  • 簡寫方式隻是實現的瞭標準寫法中的get方法。
  • 賦值隻會觸發標準方式中的set方法,然後你可以得到新的值,完成一些別的工作。

1.2 案例-購物車合計使用計算屬性

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>vue學習使用</title>
        <!-- 第1步: 引入vue庫文件 -->
        <script src="./js/vue.js"></script>
    </head>
    <body>
        <!-- 第2步:掛載點 -->
        <div id="app">
            <table border="1" width="600">
                <tr>
                    <th>序號</th>
                    <th>名稱</th>
                    <th>單價</th>
                    <th>數量</th>
                    <th>操作</th>
                </tr>
                <tr v-for="item,index in carts">
                    <td>{{index+1}}</td>
                    <td>{{item.name}}</td>
                    <td>{{item.price}}</td>
                    <td>
                        <button @click="setNum(1,index)">+++</button>
                        <input type="number" v-model="item.num">
                        <button @click="setNum(-1,index)">---</button>
                    </td>
                    <td>
                        <button @click="del(index)">刪除</button>
                    </td>
                </tr>
            </table>
            <hr>
            <h3>
                合計:
                {{totalPrice}}
            </h3>
        </div>
        <!-- 第3步:實例化vue -->
        <script>
            const vm = new Vue({
                el: '#app',
                data: {
                    carts: [
                        { id: 1, name: '小米12pro', price: 1, num: 1 },
                        { id: 2, name: '華為手機', price: 2, num: 1 },
                        { id: 3, name: '水果手機', price: 3, num: 1 },
                    ]
                },
                methods: {
                    setNum(n, index) {
                        this.carts[index].num += n
                        this.carts[index].num = Math.min(3, Math.max(1, this.carts[index].num))
                    },
                    del(index) {
                        confirm('確定刪除') && this.carts.splice(index, 1)
                    }
                },
                // 計算屬性
                computed: {
                    totalPrice() {
                        return this.carts.reduce((prev, { price, num }) => {
                            // 依賴項
                            prev += price * num
                            return prev
                        }, 0)
                    }
                }
            })
        </script>
    </body>
</html>

在這裡插入圖片描述

2. 偵聽器

概述:

使用watch來偵聽data中數據的變化,watch中的屬性一定是data 中已經存在的數據。

當需要監聽一個對象的改變時,普通的watch方法無法監聽到對象內部屬性的改變,隻有data中的數據才能夠監聽到變化,此時就需要deep屬性對對象進行深度監聽。

使用:

標準寫法:

<div id="app">
    <div>
        <input type="text" v-model="username">
        <span>{{errorUsername}}</span>
    </div>
</div>
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            username: '',
            errorUsername: ''
        },
        // 監聽器,它用來監聽data配置中的數據的變化,一但有變化,就會自動觸發.默認情況下,初始化不觸發
        // 在監聽器中是可以得到this對象的
        // 監聽器它的依賴項,隻有一個,一對一
        // 監聽器中可以寫異步
        watch: {
            // 方法名或屬性名 就是你要觀察的data中的屬性名稱
            // 標準寫法
            username: {
                // newValue 變化後的值;oldValue 變化前的值
                handler(newValue, oldValue) {
                    if (newValue.length >= 3) this.errorUsername = '賬號過長'
                    else this.errorUsername = ''
                }
            }
        })
</script>

在這裡插入圖片描述

註意:

  1. 監聽器用來監聽data配置中的數據的變化,一但有變化,就會自動觸發.默認情況下,初始化不觸發。
  2. 在監聽器中是可以得到this對象的。
  3. 監聽器的依賴項,隻有一個,一對一。
  4. 監聽器中可以寫異步(Ajax 或者 setTimeout)。

簡寫:

<div id="app">
    <div>
        <input type="text" v-model="username">
        <span>{{errorUsername}}</span>
    </div>
</div>
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            username: '',
            errorUsername: ''
        },
        watch: {
            username(newValue, oldValue) {
                if (newValue.length >= 3) this.errorUsername = '賬號過長'
                else this.errorUsername = ''
            }
        }
    })
</script>

在這裡插入圖片描述

初始化時,啟用偵聽器寫法:

<div id="app">
    <div>
        <input type="text" v-model="username">
        <span>{{errorUsername}}</span>
    </div>
</div>
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            username: 'aaa',
            errorUsername: ''
        },
        watch: {
            // 方法名或屬性名 就是你要觀察的data中的屬性名稱
            // 標準寫法
            username: {
                handler(newValue, oldValue) {
                    if (newValue.length >= 3) this.errorUsername = '賬號過長'
                    else this.errorUsername = ''
                },
                // 初始時,執行1次 --- 一般情況下,不啟用  隻有在標準寫法下面,才有此配置
                immediate: true
            }
        })
</script>

在這裡插入圖片描述

註意:這個配置隻有在標準寫法下才能有。

監聽對象中的屬性變化:

<div id="app">
    <div>
        <input type="number" v-model.number="user.id"> 
    </div>
</div>
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            user: { id: 100, name: 'aaa' }
        },
        // 監聽對象中的指定的屬性數據的變化  推薦如果你監聽的是一個對象中數據變化,建議這樣的方式
        watch: {
            'user.id'(newValue, oldValue){
                console.log(newValue, oldValue);
            }
        }
    })
</script>

在這裡插入圖片描述

監聽對象變化:

<div id="app">
    <div>
        <input type="number" v-model.number="user.id"> 
    </div>
</div>
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            user: { id: 100, name: 'aaa' }
        },
        watch: {
            // 監聽對象,隻能使用標準方式來寫
            // 監聽對象變化,它的前後值是一樣的,無法區分
            user: {
                // 深度監聽
                deep: true,
                handler(newValue, oldValue) {
                    console.log(newValue, oldValue);
                },
            }
        }
    })
</script>

在這裡插入圖片描述

註意:

  1. 監聽對象,隻能使用標準方式來寫
  2. 監聽對象變化,它的前後值是一樣的,無法區分

3. 過濾器

概述:

在數據被渲染之前,可以對其進行進一步處理,比如將字符截取或者將小寫統一轉換為大寫等等,過濾器本身就是一個方法。

過濾器的作用就是為瞭對於界面中顯示的數據進行處理操作。

過濾器可以定義全局或局部。

定義全局過濾器:

<div id="app">
    <h3>{{ phone | phoneCrypt }}</h3>
</div>
<script>
    // 參數1:過濾器的名稱,可以隨意起名
    // 參數2:回調函數,回調函數中的參數最少要有一個,第1位參數,永遠指向為要過濾的數據
    Vue.filter('phoneCrypt', value => {
        return value.slice(0, 3) + '~~~~' + value.slice(7)
    })
    const vm = new Vue({
        el: '#app',
        data: {
            phone: '13523235235'
        }
    })
</script>

在這裡插入圖片描述

上面的全局過濾器的回調函數中隻有一個參數,我們還可以定義多個參數:

<div id="app">
    <!-- 這裡傳的第一個參數,對應全局過濾器的回調函數中定義的第二個參數 -->
    <h3>{{ phone | phoneCrypt('!!!!') }}</h3>
</div>
<script>
    Vue.filter('phoneCrypt', (value, salt = '****') => {
        return value.slice(0, 3) + salt + value.slice(7)
    })
    const vm = new Vue({
        el: '#app',
        data: {
            phone: '13523235235'
        }
    })
</script>

在這裡插入圖片描述

定義局部過濾器:

<div id="app">
    <h3>{{ phone | phoneCrypt('!!!!') }}</h3>
</div>
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            phone: '13523235235'
        },
        // 局部過濾器
        filters:{
            phoneCrypt(value, salt = '****'){
                return value.slice(0, 3) + salt + value.slice(7)
            }
        }
    })
</script>

在這裡插入圖片描述

到此這篇關於Vue計算屬性與偵聽器和過濾器超詳細介紹的文章就介紹到這瞭,更多相關Vue計算屬性內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: