认识计算属性computed

  • 思路一的实现:模板语法

    • 缺点一:模板中存在大量的复杂逻辑,不便于维护(模板中表达式的初衷是用于简单的计算);

    • 缺点二:当有多次一样的逻辑时,存在重复的代码;

    • 缺点三:多次使用的时候,很多运算也需要多次执行,没有缓存;

  • 思路二的实现:method实现

    • 缺点一:我们事实上先显示的是一个结果,但是都变成了一种方法的调用;
    • 缺点二:多次使用方法的时候,没有缓存,也需要多次计算;

  • 思路三的实现:computed实现

    • 注意:计算属性看起来像是一个函数,但是我们在使用的时候不需要加(),这个后面讲setter和getter时会讲到;
    • 我们会发现无论是直观上,还是效果上计算属性都是更好的选择;
    • 并且计算属性是有缓存的;

计算属性的缓存

  • 这是什么原因呢?
    • 这是因为计算属性会基于它们的依赖关系进行缓存
    • 数据不发生变化时,计算属性是不需要重新计算的;
    • 但是如果依赖的数据发生变化,在使用时,计算属性依然会重新进行计算

计算属性的setter和getter

  • 计算属性在大多数情况下,只需要一个getter方法即可,所以我们会将计算属性直接写成一个函数
  • 但是,如果我们确实想设置计算属性的值呢?
    • 这个时候我们也可以给计算属性设置一个setter的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
computed: {
// 语法糖的写法
// fullname() {
// return this.firstname + " " + this.lastname
// },

// 完整的写法:
fullname: {
get: function() {
return this.firstname + " " + this.lastname
},
set: function(value) {
const names = value.split(" ")
this.firstname = names[0]
this.lastname = names[1]
}
}
},

认识侦听器watch

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
data() {
return {
message: "Hello Vue",
info: { name: "why", age: 18 }
}
},
methods: {
changeMessage() {
this.message = "你好啊, 李银河!"
this.info = { name: "kobe" }
}
},
watch: {
// 1.默认有两个参数: newValue/oldValue
message(newValue, oldValue) {
console.log("message数据发生了变化:", newValue, oldValue)
},
info(newValue, oldValue) {
// 2.如果是对象类型, 那么拿到的是代理对象
// console.log("info数据发生了变化:", newValue, oldValue)
// console.log(newValue.name, oldValue.name)

// 3.获取原生对象
// console.log({ ...newValue })
console.log(Vue.toRaw(newValue))
}
}

侦听器watch的配置选项

  • 我们先来看一个例子:
    • 当我们点击按钮的时候会修改info.name的值;
    • 这个时候我们使用watch来侦听info,可以侦听到吗?答案是不可以
  • 这是因为默认情况下,watch只是在侦听info的引用变化,对于内部属性的变化是不会做出响应的:
    • 这个时候我们可以使用一个选项deep进行更深层的侦听;
    • 注意前面我们说过watch里面侦听的属性对应的也可以是一个Object;
  • 还有另外一个属性,是希望一开始的就会立即执行一次:
    • 这个时候我们使用immediate选项
    • 这个时候无论后面数据是否有变化,侦听的函数都会有限执行一次;
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
data() {
return {
info: { name: "why", age: 18 }
}
},
methods: {
changeInfo() {
// 1.创建一个新对象, 赋值给info
// this.info = { name: "kobe" }

// 2.直接修改原对象某一个属性
this.info.name = "kobe"
}
},
watch: {
// 默认watch监听不会进行深度监听
// info(newValue, oldValue) {
// console.log("侦听到info改变:", newValue, oldValue)
// }

// 进行深度监听
info: {
handler(newValue, oldValue) {
console.log("侦听到info改变:", newValue, oldValue)
console.log(newValue === oldValue)
},
// 监听器选项:
// info进行深度监听
deep: true,
// 第一次渲染直接执行一次监听器
immediate: true
},
"info.name": function(newValue, oldValue) {
console.log("name发生改变:", newValue, oldValue)
}
}
  • 还有另外一种方式就是使用 $watch 的API:
  • 我们可以在created的生命周期(后续会讲到)中,使用 this.$watchs来侦听;
    • 第一个参数是要侦听的源;
    • 第二个参数是侦听的回调函数callback;
    • 第三个参数是额外的其他选项,比如deep、immediate;