欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Vue学习笔记(三) 计算属性和侦听属性

程序员文章站 2022-05-17 10:10:50
...

1、计算属性(computed)

(1)computed

模板的设计初衷是处理简单的逻辑(声明式逻辑),在模板中加入过多逻辑会使模板难以阅读和维护

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Demo</title>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>

<body>
    <div id="app">
        <p>原始字符串:{{ message }}</p>
        <p>反转字符串:{{ message.split('').reverse().join('') }}</p>
    </div>

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

</html>

这时,我们就应该考虑使用计算属性,代替复杂的模板逻辑

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <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: {
                reversedMessage: function () {
                    return this.message.split('').reverse().join('')
                }
            }
        })
    </script>
</body>

</html>

这里,我们声明了一个计算属性 reversedMessage,所提供的函数将默认作为属性的 getter 函数

reversedMessage 依赖于 message,当 message 发生变化时,reversedMessage 也会自动更新

(2)computed & methods

不知道大家还记不记得,我们在第一篇文章中有一个例子,使用 methods 实现反转字符串的效果

<!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: function () {
                    return this.message.split('').reverse().join('')
                }
            }
        })
    </script>
</body>

</html>

computed 和 methods 实现的功能相同,但是它们的不同之处在于:

  1. computed 是 属性调用,而 methods 是方法调用
  2. computed 是 基于缓存,而 methods 不是

也就是说,对于计算属性(computed)而言,计算结果将会被缓存

如果某个依赖(比如非响应式属性)在该实例范畴之外,则计算属性是不会被更新的

但是对于方法(methods)而言,调用方法总会再次执行代码

我们可以从一个简单的例子看出它们之间的区别:

<!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: function () {
                    cnt_for_computed += 1;
                    return cnt_for_computed
                }
            },
            methods: {
                msg_in_methods: function () {
                    cnt_for_methods += 1;
                    return cnt_for_methods
                }
            }
        })
    </script>
</body>

</html>

<!-- 输出结果
第一次调用 computed:1
第二次调用 computed:1


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

对于 msg_in_computed 而言,第一次使用时会执行代码,msg_in_computed 的值变成 1;

第二次使用时不会执行代码,因为 cnt_for_computed 是非响应式属性,msg_in_computed 的值仍为 1

对于 msg_in_methods() 而言,每调用一次 msg_in_methods(),就执行一次代码,每次自增 1

(3)getter & setter

计算属性默认只有 getter 函数

<!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: function () {
                    return this.firstName + ' ' + this.lastName
                }
            }
        })
    </script>
</body>

</html>

但是,在需要的时候我们也可以提供一个 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]
                    }
                }
            }
        })
        vm.fullName = 'Tim Cook'
    </script>
</body>

</html>

<!-- 输出结果
fullName: Tim Cook
firstName: Tim
lastName: Cook
-->

在运行 vm.fullName = ‘Tim Cook’ 时,setter 会被调用,vm.firstName 和 vm.lastName 也会相应更新

2、侦听属性(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: function(val, oldVal){
                    alert('计数器从 ' + val + ' 变为 ' + oldVal);
                }
            }
        });
    </script>
</body>

</html>

在这里,我们声明了一个侦听属性 counter,当 counter 发生变化时,会自动调用其对应的回调函数

  • 包含选项的对象
var vm = new Vue({
    el: '#app',
    data: {
        counter: 1
    },
    watch: {
        counter: {
            handler: function (val, oldVal) {
                alert('计数器从 ' + val + ' 变为 ' + oldVal);
            },
            deep: true, // 当监听对象的属性发生变化时(不管嵌套的深度),触发回调
            immediate: true // 在侦听开始之后,立即触发回调
        },
    }
});
我们已经学习了什么?—— 选项
  • 数据
    • data √
    • methods √
    • computed √
    • watch√
    • props
    • propsData
  • DOM
    • el √
    • template
    • render
    • renderError
  • 生命钩子函数
  • 资源
  • 组合
  • 其它