Vue學習筆記(三) 計算屬性和偵聽屬性

一、計算屬性(computed)

(1)計算屬性javascript

模板的設計初衷是爲了處理簡單的邏輯(即聲明式邏輯),在模板中加入過多的邏輯會使模板難以閱讀和維護html

<!DOCTYPE html>
<html>

<head>
    <title>Demo</title>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>

<body>
    <div id="app">
        <p>原始字符串:{{ message }}</p>
        <!-- 好比說,在模板中對 message 進行復雜的字符串反轉操做 -->
        <p>反轉字符串:{{ message.split('').reverse().join('') }}</p>
    </div>

    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                message: 'hello'
            }
        })
    </script>
</body>

</html>

這時,咱們就應該考慮使用計算屬性,以代替複雜的模板邏輯vue

<!DOCTYPE html>
<html>

<head>
    <title>Demo</title>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>

<body>
    <div id="app">
        <p>原始字符串:{{ message }}</p>
        <!-- 在模板中直接使用計算屬性 -->
        <p>反轉字符串:{{ reversedMessage }}</p>
    </div>

    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                message: 'hello'
            },
            // computed 是 Vue 實例的計算屬性
            // 它能夠是一個對象,其中每一項的鍵是計算屬性的名稱,值是計算屬性對應的函數
            computed: {
                // 這裏,咱們聲明計算屬性 reversedMessage,用於儲存反轉以後的字符串
                // 所提供的函數默認做爲計算屬性的 getter 函數(事實上還能夠提供 setter 函數)
                // 這裏的計算屬性 reversedMessage 依賴於 message
                // 也就是說,當 message 發生變化時,reversedMessage 會自動更新
                reversedMessage: function () {
                    return this.message.split('').reverse().join('')
                }
            }
        })
    </script>
</body>

</html>

(2)computed & methodsjava

不知道你們還記不記得,咱們在以前的文章中有一個例子,使用 methods 實現反轉字符串的效果npm

<!DOCTYPE html>
<html>

<head>
    <title>Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>

<body>
    <div id="app">
        <p>原始字符串:{{ message }}</p>
        <!-- 在模板中顯示方法的返回結果 -->
        <p>反轉字符串:{{ reversedMessage() }}</p>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                message: "Hello Vue"
            },
            methods: {
                // 定義方法 reversedMessage(),返回反轉以後的字符串
                reversedMessage: function () {
                    return this.message.split('').reverse().join('')
                }
            }
        })
    </script>
</body>

</html>

能夠看到,使用 computed 和 methods 實現的功能大致相同,可是它們的不一樣之處在於:緩存

  1. computed 是 屬性調用,而 methods 是方法調用
  2. computed 是 基於緩存,而 methods 不是

對於計算屬性而言,計算結果將會被緩存,若是某個依賴在該實例範疇以外,那麼計算屬性是不會被更新的app

可是對於方法而言,調用方法總會再次執行代碼,咱們能夠從一個簡單的例子看出它們之間的區別:函數

<!DOCTYPE html>
<html>

<head>
    <title>Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>

<body>
    <div id="app">
        <!-- 注意,這裏是屬性調用 -->
        <p>第一次調用 computed:{{ msg_in_computed }}</p>
        <p>第二次調用 computed:{{ msg_in_computed }}</p>
        <br/>
        <!-- 注意,這裏是方法調用 -->
        <p>第一次調用 methods:{{ msg_in_methods() }}</p>
        <p>第二次調用 methods:{{ msg_in_methods() }}</p>
    </div>
    <script>
        var cnt_for_computed = 0;
        var cnt_for_methods = 0;
        var vm = new Vue({
            el: '#app',
            computed: {
                // 定義計算屬性 msg_in_computed,屢次調用不會更新數據
                // 由於它的依賴 cnt_for_computed 是非響應式屬性,不在實例範疇以內
                msg_in_computed: function () {
                    cnt_for_computed += 1;
                    return cnt_for_computed
                }
            },
            methods: {
                // 定義方法 msg_in_methods(),每次調用總會執行代碼
                msg_in_methods: function () {
                    cnt_for_methods += 1;
                    return cnt_for_methods
                }
            }
        })
    </script>
</body>

</html>

<!-- 輸出結果
第一次調用 computed:1
第二次調用 computed:1


第一次調用 methods:1
第二次調用 methods:2
-->

(3)getter & setter學習

計算屬性默認只有 getter 函數this

<!DOCTYPE html>
<html>

<head>
    <title>Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>

<body>
    <div id="app">
        <p>fullName: {{ fullName }}</p>
        <p>firstName: {{ firstName }}</p>
        <p>lastName: {{ lastName }}</p>
    </div>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                firstName: 'Steve',
                lastName: 'Jobs'
            },
            computed: {
                // 若爲計算屬性提供一個函數,則該函數默認做爲計算屬性的 getter 函數
                fullName: function () {
                    return this.firstName + ' ' + this.lastName
                }
            }
        })
        // 修改計算屬性依賴的值時,會自動調用計算屬性的 getter 函數
        vm.firstName = 'Stephen'
    </script>
</body>

</html>

<!-- 輸出結果
fullName: Stephen Jobs
firstName: Stephen
lastName: Jobs
-->

可是,在須要的時候咱們也能夠提供一個 setter 函數

<!DOCTYPE html>
<html>

<head>
    <title>Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>

<body>
    <div id="app">
        <p>fullName: {{ fullName }}</p>
        <p>firstName: {{ firstName }}</p>
        <p>lastName: {{ lastName }}</p>
    </div>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                firstName: 'Steve',
                lastName: 'Jobs'
            },
            computed: {
                fullName: {
                    // getter 函數
                    get: function () {
                        return this.firstName + ' ' + this.lastName
                    },
                    // setter 函數
                    set: function (newValue) {
                        var names = newValue.split(' ')
                        this.firstName = names[0]
                        this.lastName = names[names.length - 1]
                    }
                }
            }
        })
        // 修改計算屬性的值時,會自動調用計算屬性的 setter 函數
        vm.fullName = 'Tim Cook'
    </script>
</body>

</html>

<!-- 輸出結果
fullName: Tim Cook
firstName: Tim
lastName: Cook
-->

二、偵聽屬性(watch)

偵聽屬性是一個對象,鍵是須要觀察的表達式,值是 對應的回調函數 或者是 包含選項的對象

  • 對應的回調函數
<!DOCTYPE html>
<html>

<head>
    <title>Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>

<body>
    <div id="app">
        <p>計數器: {{ counter }}</p>
        <button @click="counter++">點我</button>
    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                counter: 1
            },
            watch: {
                // 當 counter 發生變化時,會自動調用其對應的回調函數打印一條信息
                counter: function(val, oldVal){
                    alert('計數器從 ' + val + ' 變爲 ' + oldVal);
                }
            }
        });
    </script>
</body>

</html>
  • 包含選項的對象
var vm = new Vue({
    el: '#app',
    data: {
        counter: 1
    },
    watch: {
        // 使用對象能夠爲監聽屬性添加更多的配置信息
        counter: {
            handler: function (val, oldVal) {
                alert('計數器從 ' + val + ' 變爲 ' + oldVal);
            },
            deep: true, // 當監聽對象的屬性發生變化時(無論嵌套的深度),觸發回調
            immediate: true // 在偵聽開始以後,當即觸發回調
        },
    }
});

【 閱讀更多 Vue 系列文章,請看 Vue學習筆記

相關文章
相關標籤/搜索