# 6. Vue watch、computed

# 使用watch监听器

# 描述

在Vue的构造选项中,提供了一个watch的对象,该对象作用于监听相关的处理,可以监听Vue实例中的属性,比如data中的数据,和监听路由等..

关键代码:watch

示例:

var vm = new Vue({
    el: '#app',
    data: {},
    methods: {},
    watch: {
        // watch监听器
    }
})
1
2
3
4
5
6
7
8

# 监听data数据改变

使用watch监听data中的数据改变。


<body>
    <div id='#app'>
        您输入的次数:
        <input type='text' v-model='value'>
        <h3>{{ num }}</h3>
    </div>
</body>
<script>


    var vm = new Vue({
        el: '#app',
        data: {
            num: 0
        },
        methods: {},
        watch: {
            'num': function (newVal,oldVal) {
                console.info(newVal, oldVal)
                this.num++;
            }
        }
    })

</script>

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

# 监听路由跳转

使用watch监听路由的path改变。

我们知道可以在vue的实例中通过this.$route.path获得路由地址,所以直接在watch中使用$route.path进行监听。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <!-- 引入Vue路由依赖js -->
    <script src="https://unpkg.com/vue-router@3.0.1/dist/vue-router.js"></script>
</head>

<body>
    <div id="app">
        <router-link to='/login'>login</router-link>
        <router-link to='/register'>register</router-link>
        <!-- 容器 -->
        <router-view></router-view>
        <!-- 欢迎消息 -->
        <h3>{{ wecomeMsg }}</h3>
    </div>
</body>

<script>
    var login = {
        template: '<h3>这是登录子组件</h3>'
    }
    var register = {
        template: '<h3>这是注册子组件</h3>'
    }
    var router = new VueRouter({
        routes: [
            // 路由规则
            { path: '/', redirect: '/login' },
            { path: '/login', component: login },
            { path: '/register', component: register }
        ]
    })
    var vm = new Vue({
        el: '#app',
        data: {
            wecomeMsg: ''
        },
        methods: {},
        router,
        watch: {
            // this.$route.path
            '$route.path': function (newVal, oldVal) {
                if (newVal === '/login') {
                    this.wecomeMsg = '欢迎进入登录页面,使用watch监听路由!'
                    return
                }
                if (newVal === '/register') {
                    this.wecomeMsg = '欢迎进入注册页面,使用watch监听路由!'
                    return
                }
                this.wecomeMsg = ''
            }
        }
    })
</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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

# 计算属性对象

关键代码:computed

# 描述

计算属性将被混入到 Vue 实例中。所有 gettersetterthis 上下文自动地绑定为 Vue 实例。

注意: 如果你为一个计算属性使用了箭头函数,则 this 不会指向这个组件的实例,不过你仍然可以将其实例作为函数的第一个参数来访问。

如下面所示:

computed: {
  aDouble: vm => vm.a * 2
}
1
2
3

计算属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。注意,如果某个依赖 (比如非响应式属性) 在该实例范畴之外,则计算属性是不会被更新的。

上述为官方的解释,理解一下这段话,大致意思是如下:

在该computed对象中定义的属性成为计算属性,计算属性自带了getset的方法,当我们在getset的方法中调用的data属性发生改变时Vue就会执行它。

计算后的结果会缓存起来,只要调用的data属性不发生改变,下次调用计算属性时就会直接从缓存中获取该结果进行使用。

# 特点

  1. 计算属性在引用时一定不能加括号()去调用,直接把它当作普通属性使用即可。
  2. 只要计算属性内部方法调用的data属性发生了任何变化,都会立刻重新执行方法并返回结果。
  3. 计算属性的结果会被缓存,下次调用会从缓存中获取。

# 用法

下面为官方示例:

var vm = new Vue({
  data: { a: 1 },
  computed: {
    // 仅读取
    aDouble: function () {
      return this.a * 2
    },
    // 读取和设置
    aPlus: {
      get: function () {
        return this.a + 1
      },
      set: function (v) {
        this.a = v - 1
      }
    }
  }
})
vm.aPlus   // => 2
vm.aPlus = 3
vm.a       // => 2
vm.aDouble // => 4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

自行测试示例

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="./lib/vue/vue.js"></script>
</head>

<body>
    <div id="app">
        <input type="text" v-model='firstName'> +
        <input type="text" v-model='lastName'> =
        <input type="text" v-model='fullName'>
    </div>
</body>

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            firstName: '',
            lastName: ''
        },
        methods: {},
        // 计算属性定义在computed对象中。
        computed: {
            fullName: function () {
                return this.firstName + '-' + this.lastName
            }

        }
    })

</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
37
38
39
最近更新: 2019/10/17 上午4:20:42