Vue3---methods、computed、watch的-进阶解读-与-案例

183 阅读3分钟

#完整原文地址见简书www.jianshu.com/p/09f55406e…



#本文内容提要

  • this指针 指的是对应的 Vue实例

  • 【methods】插值表达式中 可以使用函数调用返回结果

  • 【computed】计算属性的 用法

  • 注意——computed模板 和 methods模板 其计算属性的区别

  • 【watch】模板的 用法

  • 【watch】 可以实现类似 【computed】的效果

  • 当用computedmethods都可以实现时, 推荐使用computed,因为computed有缓存机制; 当用computedwatch都可以实现时, 也推荐使用computed,因为computed编写开发起来更简洁;



####this指针 指的是对应的 Vue实例 板块中的this指针(下面以methods板块为例),指的是Vue实例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="heheApp"></div>
</body>
  <script>
    const app = Vue.createApp({
        data() {
            return {
                heheString: 'luelueluelielielie',
                event:'click'
            }
        },
        methods:{
            handleClick(){
                console.log('你戳到我啦————!', this.heheString);
            }
        },
        template: `
        <div @[event]="handleClick">{{heheString}}</div>`
    });
    const vm = app.mount('#heheApp');
  </script>
</html>

methods板块为例,运行时, 可以看到this.heheString打印的数据, 正式这边对应Vue实例的heheString字段的值——luelueluelielielie


####【methods】插值表达式中 可以使用函数调用返回结果 **代码如下,代码`
{{changeString(heheString)}}
`中,使用函数调用 返回结果:** ``` Hello World! heheheheheheda
``` 运行结果:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/db5afba3286e40dcbf19dc525cf8b734~tplv-k3u1fbpfcp-zoom-1.image)
####【computed】计算属性的 用法 ``` Hello World! heheheheheheda
``` **Vue 的 `computed`属性, 可以在这里定义计算逻辑属性,使用`data()`中的数据,计算得到结果, 供给`template`使用、渲染显示; `template`中可以通过`插值表达式`使用`computed`中的值, 运行结果:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9f60c947b4c741899e3ae7cdf6d8f003~tplv-k3u1fbpfcp-zoom-1.image)动态改变data的数据时, 对应的 `computed`中定义的属性、对应的`template`中的DOM节点, 都会发生对应的改变:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2f8d4167779144f6bbc9eaa48ff9e88e~tplv-k3u1fbpfcp-zoom-1.image)**

#####注意——computed模板 和 methods模板 其计算属性的区别 ---首先,【computed】内部会带有一种缓存机制, 在进行页面渲染的时候会更加高效, computed模板 和 methods模板 都可以使用的情况下,推荐使用【computed】;
---接着,【computed】模板: 当【computed】定义的计算属性 依赖的 【data】数据发生变化时, 计算属性才会重新计算和更新,如上面的例子;
而 当 只是页面重新渲染时, 计算属性不会重新计算和更新,不会重新执行;
如下, 我们通过改变文本DOM节点对应绑定的data数据,使得页面重新渲染, 可以看到, 右侧的数据DOM节点没有变化,计算属性不会重新计算和更新;

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="heheApp"></div>
</body>
  <script>
    const app = Vue.createApp({
        data() {
            return {
                heheString: 'luelueluelielielie',
                event:'click',
                testCount: 6,
                testPrice: 6
            }
        },
        computed:{
            testTotal() {
                // return this.testCount * this.testPrice;
                return Date.now();
            }
        },
        methods:{
            changeString(string){
                // console.log('你戳到我啦————!', this.heheString);
                return string.toUpperCase();
            },
            testGetTotal() {
                return Date.now();
            }
        },
        template: `
        <div>{{heheString}} {{testTotal}}</div>`
    });
    const vm = app.mount('#heheApp');
  </script>
</html>

【methods】模板: 当页面重新渲染时, 【methods】模板下的内容会被 重新计算更新重新执行

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="heheApp"></div>
</body>
  <script>
    const app = Vue.createApp({
        data() {
            return {
                heheString: 'luelueluelielielie',
                event:'click',
                testCount: 6,
                testPrice: 6
            }
        },
        computed:{
            testTotal() {
                // return this.testCount * this.testPrice;
                return Date.now();
            }
        },
        methods:{
            changeString(string){
                // console.log('你戳到我啦————!', this.heheString);
                return string.toUpperCase();
            },
            testGetTotal() {
                return Date.now();
            }
        },
        template: `
        <div>{{heheString}} {{testGetTotal()}}</div>`
    });
    const vm = app.mount('#heheApp');
  </script>
</html>

测试手法如上例, 可以看到页面重新渲染时, DOM文本节点发生变化, 因为【methods】模板下的内容重新执行了:


####【watch】模板的 用法 **作用: 监听data字段的改变, 当对应设置的 被监听字段 发生变化时,回调会被触发执行, 可以进行异步操作;**

如下案例, 我们监听一下testPrice字段, 当其发生改变时,延时2800ms后打印一个log:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="heheApp"></div>
</body>
  <script>
    const app = Vue.createApp({
        data() {
            return {
                heheString: 'luelueluelielielie',
                event:'click',
                testCount: 6,
                testPrice: 6
            }
        },
        watch:{
            testPrice(){
                setTimeout(() => {
                    console.log('testPrice changed');
                },2800);
            }
        },
        computed:{
            testTotal() {
                // return this.testCount * this.testPrice;
                return Date.now();
            }
        },
        methods:{
            changeString(string){
                // console.log('你戳到我啦————!', this.heheString);
                return string.toUpperCase();
            },
            testGetTotal() {
                return Date.now();
            }
        },
        template: `
        <div>{{heheString}} {{testGetTotal()}}</div>`
    });
    const vm = app.mount('#heheApp');
  </script>
</html>

关键代码:

        watch:{
            testPrice(){
                setTimeout(() => {
                    console.log('testPrice changed');
                },2800);
            }
        }

运行效果:


#####watch 的 current、prev参数 ``` Hello World! heheheheheheda
``` 关键代码: ``` watch:{ testPrice(current, prev){ console.log('current -- testPrice: ', current, ' prev -- testPrice', prev); } }, ``` **可以通过这两个`回调参数`,监听到数据`改变前后的值`:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2b4179cc8c104278a85b39edc85664fa~tplv-k3u1fbpfcp-zoom-1.image)**
#####【watch】 可以实现类似 【computed】的效果 **利用Vue的MVVM双向绑定特性, 【watch】 可以实现类似 【computed】的效果, 但实际开发效率低于【computed】,`基本上是不使用这样的方案的`:** ``` ...
``` 运行效果:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fccf947d8e6a4508bfeae60c36bae69f~tplv-k3u1fbpfcp-zoom-1.image)手动改变 被监听的data字段(testPrice), 触发watch回调, watch回调中,计算新值并覆盖到 data对应的字段中(newTestTotal), data对应的用于显示的字段(newTestTotal)发生改变, UI重新渲染:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f4e28f6067134b79af6f1e8a9bf3f63e~tplv-k3u1fbpfcp-zoom-1.image)