H5W3
当前位置:H5W3 > 其他技术问题 > 正文

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的实现方式应该没啥区别,我看官网的文档也没有详细的说明,但是这个例子看来,这两者还是有区别的,有没有大神能给解惑的?

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

回答

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

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

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

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

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

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

https://github.com/vuejs/vue/blob/dev/src/core/instance/state.js#L303
从源码上看是没有区别的,最终调用了同一块的代码。第一块代码中,可能你对kilometers 重新赋值后,下面那个watcher被移除了队列,所以没有执行到(具体要看看源码)

本文地址:H5W3 » vue中watch和vm.$watch方法的区别?

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址