vue中watch和vm.$watch方法的区别?

话不多说,直接上代码

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
    <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
</head>

<body>
    <div id="computed_props">
        千米 : <input type="text" v-model="kilometers"> 米 : <input type="text" v-model="meters">
    </div>
    <p id="info"></p>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#computed_props',
            data: {
                kilometers: 0,
                meters: 0
            },
            methods: {},
            computed: {},
            watch: {
                kilometers: function(newValue, oldValue) {
                    console.log('kilometers  newValue:' + newValue + ', oldValue:' + oldValue)
                    this.kilometers = newValue;
                    this.meters = this.kilometers * 1000
                },
                meters: function(newValue, oldValue) {
                    console.log('meters newValue:' + newValue + ', oldValue:' + oldValue)
                    this.kilometers = newValue / 1000;
                    this.meters = newValue;
                }
            }
        });
        // $watch 是一个实例方法
        vm.$watch('kilometers', function(newValue, oldValue) {
            console.log('实例方法')
                // 这个回调将在 vm.kilometers 改变后调用
            document.getElementById("info").innerHTML = "修改前值为: " + oldValue + ",修改后值为: " + newValue;
        })
    </script>
</body>

</html>

上面是第一段代码,在控制台打印如下:

kilometers  newValue:1, oldValue:0
meters newValue:1000, oldValue:0
kilometers  newValue:1, oldValue:1
实例方法

这里不太理解为什么“实例方法”只打印了一次,是不是watch监听的两种实现方式有区别?

第二段代码:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
    <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
</head>

<body>
    <div id="computed_props">
        千米 : <input type="text" v-model="kilometers"> 米 : <input type="text" v-model="meters">
    </div>
    <p id="info"></p>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#computed_props',
            data: {
                kilometers: 0,
                meters: 0
            },
            methods: {},
            computed: {},
            watch: {
                kilometers: function(newValue, oldValue) {
                    console.log('kilometers  newValue:' + newValue + ', oldValue:' + oldValue)

                },
                meters: function(newValue, oldValue) {
                    console.log('meters newValue:' + newValue + ', oldValue:' + oldValue)
                    this.kilometers = newValue / 1000;
                    this.meters = newValue;
                }
            }
        });
        // $watch 是一个实例方法
        vm.$watch('kilometers', function(newValue, oldValue) {
            this.kilometers = newValue;
            this.meters = this.kilometers * 1000
            console.log('实例方法')
                // 这个回调将在 vm.kilometers 改变后调用
            document.getElementById("info").innerHTML = "修改前值为: " + oldValue + ",修改后值为: " + newValue;
        })
    </script>
</body>

</html>

控制台打印如下

kilometers  newValue:1, oldValue:0
实例方法
meters newValue:1000, oldValue:0
kilometers  newValue:1, oldValue:1
实例方法

“实例方法”被打印了两次

我个人的理解是两种watch的实现方式应该没啥区别,我看官网的文档也没有详细的说明,但是这个例子看来,这两者还是有区别的,有没有大神能给解惑的?

===============================更新=======================
不会引起死循环,有疑问的可以把代码自己考下来运行一遍就清楚了

阅读 5.5k
3 个回答

第一个例子:
???你的代码没有死循环吗?
1.两个 watch 的监听相互改值
2.然后还在里面改自己的值,即使没有变更数据也是违规操作!
嗷嗷嗷!vm.$watch 在第二轮踢掉了内部那个会造成循环的监听

第二个例子:
没救了,死循环?

你的写法很危险.有引起循环调用爆栈的风险.

首先,监视一个值,然后给这个值赋watch到新值没有意义,该值是先变成新值,然后触发watch回调的.而如果给他赋另外的值,就会死循环.

另外你这里用两个watch互相给对方赋值,这种操作同样有死循环风险.

回到正题.
vue是基于配置的模式,正常情况下我们编写的就是一个实例的配置对象,这种模式写起来快而且较有条理但不灵活.
$watch就是为了补充这种灵活性缺失的API,让你可以在运行时动态的监视某个值,而且还可以在不需要时解除监视,本质上与配置里的watch没有区别.

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏