Skip to content
On this page

观察(watch)

一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性。

为什么一定要有watch,不用可以吗?我们已经有了computed,能不能不去使用?

watch的出现

做一个实验

html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>vue</title>
</head>
<body>
    <div id="app">
        <input type="text" v-model="a">
    </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script> 
<script>

    var vm = new Vue({
        el:'#app',
        data:{
            a:"1"
        },
        computed: {
            a(){
               setTimeout(() => {
                   this.a=1;
               }, 500); 
            }
        }
    })
</script>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

不难发现在_异步的情况下就不好使用了_

代码实现

javascript
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>vue</title>
</head>
<body>
    <div id="app">
        <input type="text" v-model="a">
    </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script> 
<script>
    var vm = new Vue({
        el:'#app',
        data:{
            a:""
        },
        watch: { // 只有值变化的时候才会触发 支持异步了,其他情况我们更善于使用
            a(newVal,oldVal){ // watch的属性名字要和观察的人的名字一致
                console.log(newVal);
                console.log(oldVal);
            }
        },
    })
</script>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

computed与watch的区别

Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch

javascript
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>vue</title>
</head>
<body>
    <div id="app">
        {{ fullName }}
    </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script> 
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
javascript
    var vm = new Vue({
    el: '#app',
        data: {
            firstName: 'Foo',
            lastName: 'Bar',
            fullName: 'Foo Bar'
        },
        watch: {
            firstName: function (val) {
                this.fullName = val + ' ' + this.lastName
            },
            lastName: function (val) {
                this.fullName = this.firstName + ' ' + val
            }
        }
    })
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

上面代码是命令式且重复的。将它与计算属性的版本进行比较:

javascript
var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar'
  },
  computed: {
    fullName: function () {
      return this.firstName + ' ' + this.lastName
    }
  }
})
1
2
3
4
5
6
7
8
9
10
11
12

是不是感觉优雅很多

第一点:语境上的差异:

watch适合一个值发生了变化,对应的要做一些其它的事情,适合一个值影响多个值的情形。

例如,上面案例中的用户名检测,这里是一个uname发生了变化,但是这里做了很多其它的事情,例如修改message的值,发送异步请求。

而计算属性computed:一个值由其它的值得来,其它值发生了变化,对应的值也会变化,适合做多个值影响一个值的情形。

例如如下代码:

computed:{ fullName(){ return this.firstName+' '+this.lastName } }

第二点:计算属性有缓存性。

由于这个特点,我们在实际的应用中,能用计算属性的,会首先考虑先使用计算属性。

第三点:侦听器开销

侦听器选项提供了更加通用的方法,适合执行异步操作或者较大开销操作。

侦听器

虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>vue</title>
</head>
<body>
    <div id="app">
       <input type="text" v-model="something">
       {{somethingShow}}
    </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script> 
<script>
    var vm = new Vue({
    el: '#app',
        data: {
            something: '',
            somethingShow:''
        },
        watch: {
            something(val){
                this.somethingShow = "loading"
                this.getSomething()
            }
        },
        methods:{
            getSomething(){
                setTimeout(() => {
                    this.somethingShow = "hello"
                }, 1000);// 我们使用延迟模拟一个网络请求
            }
        }
    })
</script>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

vm.$watch

vm.$watch( expOrFn, callback, [options] )

观察 Vue 实例变化的一个表达式或计算属性函数。回调函数得到的参数为新值和旧值。表达式只接受监督的键路径。对于更复杂的表达式,用一个函数取代。

html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>vue</title>
</head>
<body>
    <div id="app">
       <input type="text" v-model="something">
       {{somethingShow}}
    </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script> 
<script>
    var vm = new Vue({
    el: '#app',
        data: {
            something: '',
            somethingShow:''
        }
    })
    vm.$watch('something',(newVal,oldVal)=>{// watch的属性名要和观察的人名字一致
        vm.somethingShow = "loading"
        console.log('====================================');
        console.log(newVal);
        console.log('====================================');
        vm.somethingShow = newVal
    })
</script>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
沪ICP备20006251号-1