zoukankan      html  css  js  c++  java
  • Vue学习笔记(三) 计算属性和侦听属性

    1、计算属性(computed)

    (1)计算属性

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

    <!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>
    

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

    <!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 & 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(),返回反转之后的字符串
                    reversedMessage: function () {
                        return this.message.split('').reverse().join('')
                    }
                }
            })
        </script>
    </body>
    
    </html>
    

    可以看到,使用 computed 和 methods 实现的功能大体相同,但是它们的不同之处在于:

    1. computed 是 属性调用,而 methods 是方法调用
    2. 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,多次调用不会更新数据
                    // 因为它的依赖 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 函数

    <!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
    -->
    

    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 发生变化时,会自动调用其对应的回调函数打印一条信息
                    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学习笔记

    版权声明:本博客属于个人维护博客,未经博主允许不得转载其中文章。
  • 相关阅读:
    js 动态 activex 组件
    nodejs 任务调度使用
    javascript 停止事件冒泡以及阻止默认事件冒泡
    使用SQL字符串反转函数REVERSE巧妙实现lastindexof功能
    morris.js 简单学习
    weblogic启动受管服务器报错Authentication for user weblogic denied (weblogic 11g 域账号密码不生效的解决方法)
    正向代理与反向代理【总结】
    不休息的工作都是浪费时间
    Oracle实例名,服务名等概念区别与联系
    Tomcat启动找不到JRE_HOME的解决方法
  • 原文地址:https://www.cnblogs.com/wsmrzx/p/11199037.html
Copyright © 2011-2022 走看看