2022/11/19 vue-metheds/computed/watch

87 阅读2分钟

metheds

先上一段代码,这段代码里有两个变量 counter和name,分别使用按钮和输入框改变他们,通过插值表达式显示它们。

    <div id="app">
        <button v-on:click="add">add</button>
        <p>{{ counter }}</p>
        <input v-model="name">
        <p>{{ getFullname() }}</p>
    </div>
    <script>
        const app = Vue.createApp({
            data() {
                return {
                    name: '',
                    counter: 0
                }
            },
            methods: {
                getFullname() {
                    console.log('getFullname...')
                    if (this.name) {
                        return this.name + 'WU'
                    }
                    return ''
                },
                add() {
                    this.counter ++
                }
            }
        })
        app.mount('#app')
    </script>

在使用name的时候使用了方法拼接一个字符串用于显示,可以起到我们输入的同时改变显示的内容。 但是当我们点击按钮改变counter的时候,控制台依旧在输出 getFullname...

总结一下:

当在data中定义且在页面中使用了的变量发生改变时,这个页面上的非事件绑定的渲染相关方法都会被重新调用。

因为vue不知道这些方法的内部有没有用到改变的data,都会去执行一遍,所以一些需要动态计算的值使用metheds会影响性能。

computed

当我们使用computed时,就可以避一些性能消耗了,当我们再次点击按钮改变counter的时候,不会再执行fullname这个计算属性,因为vue会找到这个计算属性的依赖值,在这个例子中是name,只有name的值发生改变的时候,才会重新执行fullname。

    <div id="app">
        ...
        <p>{{ fullname }}</p>
    </div>
    <script>
        const app = Vue.createApp({
            data() {
               ...
            },
            computed: {
                fullname() {
                    console.log('fullname...')
                    if (this.name) {
                        return this.name + 'WU'
                    }
                    return ''
                },
            },
            methods: {
                ...
            }
        })
        app.mount('#app')
    </script>

watch

上述使用computed实现的效果利用watch也可以做到:

    <div id="app">
       ...
        <p>{{ fullname }}</p>
    </div>
    <script>
        const app = Vue.createApp({
            data() {
                return {
                    name: '',
                    counter: 0,
                    fullname: ''
                }
            },
            watch: {
                // 将data或computed中的数据作为watch方法的名称
                // 每次当name改变时,这个watch都会被重新执行
                // watch方法接收两个参数,第一个参数是依赖项的最新值,第二个参数是依赖项先前的值
                name(value, oldValue) {
                    console.log('name...')
                    // 参数value就是this.name的最新值
                    if (value) {
                        this.fullname =  value + 'WU'
                    }
                }
            },
            methods: {
                ...
            }
        })
        app.mount('#app')
    </script>

当一个值的改变依赖多个data时,使用watch就需要多个方法,分别监听不同的数据。

虽然一个功能使用了三种写法,但是上面的案例,最好的用法还是使用computed。

比较一下~

methods可以被使用在模板中绑定数据也可以用于事件绑定。但是当methods被使用在模板中绑定数据时,任意用于页面的data的改变,都会触发methods的重新执行。

computed只用于数据绑定,适合生成基于其他数据的数据,它们只会在依赖项改变时重新执行。

watch不直接使用在模板中,用于响应一些更改数据的代码,比如发生请求/设置定时器/本地存储...,所以应该使用watch做一些非数据更新的事情。