Computed(计算属性)

当其依赖的属性的值发生变化时,计算属性会重新计算,反之,则使用缓存中的属性值。

计算函数,复杂的计算都应该放在这里,尽量不要直接在模板语法里面计算,在此处计算的值是会动态变的,即计算的数中有一个值变了,最终结果也会跟着变

我们直接来例子:

  1. // 引用完整版 Vue
  2. import Vue from "vue/dist/vue.js";
  3. Vue.config.productionTip = false;
  4. new Vue({
  5. data() {
  6. return {
  7. num1: 10,
  8. num2: 20,
  9. nums: 5
  10. };
  11. },
  12. computed: {
  13. addNum: {
  14. get() {
  15. return Number(this.nums) + Number(this.num1) + Number(this.num2);
  16. },
  17. set(value) {
  18. console.log(value);
  19. }
  20. }
  21. },
  22. template: `
  23. <div>
  24. // 这里就是计算出来的addNum
  25. {{addNum}}
  26. </div>
  27. </div>
  28. `,
  29. methods: {}
  30. }).$mount("#app");

上面代码就用到了computed。如果有很大的计算量的代码。就可以放在computed里面这样不会让你的代码看着很凌乱,让你的代码的逻辑看着更加的清晰,还有如果修改了里面的值,他会自动发更新结果。

看的不是很明白?

  1. // 引用完整版 Vue
  2. import { has } from "core-js/core/dict";
  3. import Vue from "vue/dist/vue.js";
  4. Vue.config.productionTip = false;
  5. let id = 0;
  6. const createUser = (name, gender) => {
  7. id += 1;
  8. return { id, name, gender };
  9. };
  10. new Vue({
  11. data() {
  12. return {
  13. users: [
  14. createUser("方方", "男"),
  15. createUser("圆圆", "女"),
  16. createUser("小新", "男"),
  17. createUser("小葵", "女")
  18. ],
  19. gender:""
  20. };
  21. },
  22. computed:{
  23. displayUsers(){
  24. const hash = {
  25. male:'男',
  26. female: '女'
  27. }
  28. const {users ,gender}= this;
  29. if (gender === '') {
  30. return this.users
  31. }else if (typeof gender === string){
  32. return this.users.filter(u=>u.gender === hash[gender]);
  33. }
  34. }
  35. },
  36. methods:{
  37. setGender(string){
  38. this.gender = string
  39. }
  40. },
  41. // 如何给三个按钮加事件处理函数
  42. // 使用 computed
  43. template: `
  44. <div>
  45. <div>
  46. <button @click="setGender('')">全部</button>
  47. <button @click="setGender('male')">男</button>
  48. <button @click="setGender('female')">女</button></div>
  49. <ul>
  50. <li v-for="u in displayUsers" :key="u.id">
  51. {{u.name}} - {{u.gender}}
  52. </li>
  53. </ul>
  54. </div>
  55. `
  56. }).$mount("#app");

这里的computed就是一个稍微大一点的计算量了。可以看到,我们在里面有个对于性别的判断。获取性别后就会去过滤,是的在点击按钮时出现相同性别的信息。

注意

computed是有缓存的,也就是,如果依赖的属性没有变化,技术属性就不会在算一次。

我们看上面的例子。如我们点击全部,男,女。都会进行计算,但是如果我们连续的点击单独的一个按钮,他不会每次都计算,只会计算一次。

getter I setter默认不会做缓存,Vue 做了特殊处理。

Watch(侦听)

官方文档

用途:用户在数据变化的时候,执行一个函数。

  1. // 引用完整版 Vue
  2. import Vue from "vue/dist/vue.js";
  3. Vue.config.productionTip = false;
  4. new Vue({
  5. data: {
  6. n: 0,
  7. history: [],
  8. inUndoMode: false
  9. },
  10. watch: {
  11. n: function(newValue, oldValue) {
  12. console.log(this.inUndoMode);
  13. if (!this.inUndoMode) {
  14. this.history.push({ from: oldValue, to: newValue });
  15. }
  16. }
  17. },
  18. // 不如用 computed 来计算 displayName
  19. template: `
  20. <div>
  21. {{n}}
  22. <hr />
  23. <button @click="add1">+1</button>
  24. <button @click="add2">+2</button>
  25. <button @click="minus1">-1</button>
  26. <button @click="minus2">-2</button>
  27. <hr/>
  28. <button @click="undo">撤销</button>
  29. <hr/>
  30. {{history}}
  31. </div>
  32. `,
  33. methods: {
  34. add1() {
  35. this.n += 1;
  36. },
  37. add2() {
  38. this.n += 2;
  39. },
  40. minus1() {
  41. this.n -= 1;
  42. },
  43. minus2() {
  44. this.n -= 2;
  45. },
  46. undo() {
  47. const last = this.history.pop();
  48. this.inUndoMode = true;
  49. console.log("ha" + this.inUndoMode);
  50. const old = last.from;
  51. this.n = old; // watch n 的函数会异步调用
  52. this.$nextTick(() => {
  53. this.inUndoMode = false;
  54. });
  55. }
  56. }
  57. }).$mount("#app");

整个代码就实现了,当我们对一个数进行加减时,watch会侦听这个动作,然后记录下来。

29 Vue构造选项进阶属性 - 图1

同时watch还能模拟computed代码示例

什么是变化

我们直接看代码

  1. // 引用完整版 Vue,方便讲解
  2. import Vue from "vue/dist/vue.js";
  3. Vue.config.productionTip = false;
  4. new Vue({
  5. data: {
  6. n: 0,
  7. obj: {
  8. a: "a"
  9. }
  10. },
  11. template: `
  12. <div>
  13. <button @click="n += 1">n+1</button>
  14. <button @click="obj.a += 'hi'">obj.a + 'hi'</button>
  15. <button @click="obj = {a:'a'}">obj = 新对象</button>
  16. </div>
  17. `,
  18. watch: {
  19. n() {
  20. console.log("n 变了");
  21. },
  22. obj() {
  23. console.log("obj 变了");
  24. },
  25. "obj.a": function() {
  26. console.log("obj.a 变了");
  27. }
  28. }
  29. }).$mount("#app");

这个代码实现的功能是:当我们点击按钮可以观察谁真正的变动了,例如我们点击了第一个按钮就会出现如下:

29 Vue构造选项进阶属性 - 图2

显示 n 变了。

这里得出结论:

  • 如果把简单的数据类型变了 也就是上面的 n += 1那么他就是变化了。
  • 如果把对象里面的一个属性的值变了。也就是 obj.a += 'hi。对象里面的值变了,但是对象是没有变的,原因就是对象存的是一个固定的地址。
  • 如果地址改了那么对象才会变化。

如果我们想要对象里面的值obj.a变动了告诉对象obj你也变化了.

就可以用 deep:true

  1. watch: {
  2. n() {
  3. console.log("n 变了");
  4. },
  5. obj: {
  6. handler(){
  7. console.log("obj 变了");
  8. },
  9. deep:true
  10. },
  11. }

那么我们得出:

如果obj.a变了,请问obj算不算也变了

  • 如果你需要答案是「也变了」
    那么就用deep : true
  • 如果你需要答案是「没有变」
    那么就用deep:false
  • deep的意思是,监听object的时候是否往深了看

watch后面不能用箭头函数,this会指向全局对象

computed 和 watch 的区别

computed就是计算属性。

computed就是计算一个属性的,调用他的时候不需要加括号。

二是,他会根据依赖自动缓存功能,如果依赖不变,他就不会去重新计算。

watch就是监听、侦听。

如果一个属性变化了我们就去执行一个函数。

支持异步的

watch有2个选项。

  • 1个是 immediate:表示 是否在第一次渲染的时候执行函数。
  • 2个是 deep:如果我们监听一个对象,是否要看对象里面的变化。

资料来源:饥人谷

本文为贰贰的原创文章,著作权归本人和饥人谷所有,转载务必注明来源