computed计算属性

不重复做的原则
一个数据在模板中的很多地方都使用了,如果要改某个数据属性,那就要把所有地方都重改一遍。

  1. data(){
  2. user:{
  3. email:'fangfang',
  4. nickname:'方方',
  5. phone:'11828284876'
  6. }
  7. },
  8. template:`
  9. <div>
  10. {{user.nickname||user.phone||user.email}}
  11. </div>
  12. {{user.nickname||user.phone||user.email}}
  13. `

用computed可以解决这个问题,displayName是根据其他属性计算而来的属性。

  1. computed:{
  2. displayName(){
  3. const user = this.user
  4. return user.nickname||user.phone||user.email
  5. }
  6. },
  7. template:`
  8. <div>{{displayName}}</div>
  9. {{displayName}}
  10. `

要修改属性,可以用key:function;也可以用get和set

get和set方式来修改:

  1. data(){
  2. user:{
  3. email:'fangfang',
  4. nickname:'方方',
  5. phone:'11828284876'
  6. }
  7. },
  8. computed:{
  9. displayName:{ //注意这里变成对象了
  10. get(){
  11. const user = this.user
  12. return user.nickname||user.phone||user.email
  13. },
  14. set(value){
  15. this.user.nickname = value
  16. }
  17. }
  18. }

computed的缓存

如果依赖的属性没有变化,就不会重新计算
getter/setter默认不会做缓存,Vue做了特殊处理

watch监听

用途:当数据变化时,执行一个函数。也就是根据数据的变化做一些其他操作。
注意:watch是不监听第一次的值的。就是出生时的值。

撤销例子

  1. new Vue({
  2. data(){
  3. n:0,
  4. history:[],
  5. inUndoMode:false
  6. },
  7. watch:{
  8. n(newValue,oldValue){
  9. if(!this.inUndoMode){
  10. this.history.push({from:oldValue,to:newValue})
  11. }
  12. }
  13. },
  14. template:`
  15. <div>
  16. {{n}}
  17. <button @click="add1">+1</button>
  18. <button @click="add2">+2</button>
  19. <button @click="minus1">-1</button>
  20. <button @click="minus2">-2</button>
  21. <hr/>
  22. <button @click="undo">撤销</button>
  23. </div>
  24. `,
  25. methods:{
  26. add1(){
  27. this.n += 1
  28. },
  29. add2(){
  30. this.n += 2
  31. },
  32. minus1(){
  33. this.n -= 1
  34. },
  35. minus2(){
  36. this.n -= 2
  37. },
  38. undo(){
  39. const last = this.history.pop()
  40. const old = last.from
  41. this.inUndoMode = true
  42. this.n = old
  43. //$nextTick是达到setTimeout的效果,是vue提供给watch异步时使用的
  44. this.$nextTick(()=>{
  45. this.inUndoMode = false
  46. },0)
  47. }
  48. }
  49. }).$mount("#app")

下面是watch模拟computed的例子,说实话,这样做很傻!

handle()是处理变化的。immediate:true表示第一次也运行一下。

  1. new Vue({
  2. data(){
  3. user:{
  4. email:'fangfang@qq.com',
  5. nickname:'方方',
  6. phone:'13817274638'
  7. },
  8. displayName:''
  9. },
  10. watch:{
  11. 'user.email':{
  12. handler(){
  13. const {user:{email,nickname,phone}} = this
  14. this.displayName = nickname || email || phone
  15. },
  16. immediate:true
  17. },
  18. 'user.phone':{
  19. handler(){
  20. const {user:{email,nickname,phone}} = this
  21. this.displayName = nickname || email || phone
  22. },
  23. immediate:true
  24. },
  25. 'user.nickname':{
  26. handler(){
  27. const {user:{email,nickname,phone}} = this
  28. this.displayName = nickname || email || phone
  29. },
  30. immediate:true
  31. }
  32. },
  33. tempplate:`
  34. <div>
  35. {{displayName}}
  36. <button @click="user.name=undefined">remove nickname</button>
  37. </div>
  38. `,
  39. methods:{
  40. changed(){
  41. const user = this.user
  42. this.displayName = user.nickname || user.email || user.phone
  43. }
  44. }
  45. }).$mount("#app")

小结

computed和watch都是在数据变化时执行一个函数。computed注重于依赖之间的变化和缓存。watch着重于变化时执行什么东西,而不是得出一个结果。

watch 的 deep 选项

首先看一个例子,
改变obj.a时,obj.a变了,obj还是原来的地址,所以obj没变
改变obj时,obj变了,但obj.a没变

  1. new Vue({
  2. data(){
  3. n:0,
  4. obj:{
  5. a:'a'
  6. }
  7. },
  8. template:`
  9. <div>
  10. <button @click="n += 1">n+1</button>
  11. <button @click="obj.a += 'hi'">obj.a + 'hi'</button>
  12. <button @click="obj = {a:'a'}">obj + 新对象</button>
  13. </div>
  14. `,
  15. watch:{
  16. n(){
  17. console.log("n 变了")
  18. },
  19. obj(){
  20. console.log("obj 变了")
  21. },
  22. "obj.a":function(){
  23. console.log("obj.a 变了")
  24. }
  25. }
  26. }).$mount("#app")

简单类型看值,复杂类型(对象)看地址。

deep:true是深入进去看,表示监听obj里的所有属性

  1. new Vue({
  2. data(){
  3. n:0,
  4. obj:{
  5. a:'a'
  6. }
  7. },
  8. template:`
  9. <div>
  10. <button @click="n += 1">n+1</button>
  11. <button @click="obj.a += 'hi'">obj.a + 'hi'</button>
  12. <button @click="obj = {a:'a'}">obj + 新对象</button>
  13. </div>
  14. `,
  15. watch:{
  16. n(){
  17. console.log("n 变了")
  18. },
  19. obj(){
  20. handle(){
  21. console.log("obj 变了")
  22. },
  23. deep:true //表示修改obj.a时,obj也变了
  24. },
  25. "obj.a":function(){
  26. console.log("obj.a 变了")
  27. }
  28. }
  29. }).$mount("#app")

watch的完整用法

注意:watch内不要用箭头函数,因为this指向问题。
语法一:

  1. watch:{
  2. o2:function(value,oldValue){},
  3. o3(){},
  4. 04:[f1,f2],
  5. o5:'methodName',
  6. o6:{handler:fn,deep:true,immediate:true},
  7. 'object.a':function(){}
  8. }

语法二:

  1. vm.$watch('xxx',fn,{deep:..,immediate:..})

computed和watch的区别

computed是计算属性,watch是监听意思。
computed是用来计算出一个值的,不用加括号,当作属性一样用;会根据依赖的进行自动缓存,依赖的属性不变就读取缓存,不会重新计算。
watch有两个选项,immediate和deep。deep表示监听一个对象时,是否要观察对象里面属性的变化。immediate设定第一次是否也监听。

资料来源:饥人谷