问题

image.png
image.png

什么是计算属性

image.png

各种实现的案例

image.png

1、插值语法

image.png

  1. <template id="my-app">
  2. <--! 最基本的插值 -->
  3. <h2>{{firstName + " " + lastName}}</h2>
  4. <--! 三元运算符 -->
  5. <h2>{{score >= 60 ? '及格': '不及格'}}</h2>
  6. <--! 数据进行某种转化 -->
  7. <h2>{{message.split(" ").reverse().join(" ")}}</h2>
  8. </template>
  1. data() {
  2. return {
  3. firstName: "Kobe",
  4. lastName: "Bryant",
  5. score: 80,
  6. message: "Hello World"
  7. }
  8. }

2、通过methods

image.png

  1. <template id="my-app">
  2. <h2>{{getFullName()}}</h2>
  3. <h2>{{getResult()}}</h2>
  4. <h2>{{getReverseMessage()}}</h2>
  5. </template>
  1. methods: {
  2. getFullName() {
  3. return this.firstName + " " + this.lastName;
  4. },
  5. getResult() {
  6. return this.score >= 60 ? "及格": "不及格";
  7. },
  8. getReverseMessage() {
  9. return this.message.split(" ").reverse().join(" ");
  10. }
  11. }

3、computed

image.png

  1. <template id="my-app">
  2. <h2>{{fullName}}</h2>
  3. <h2>{{result}}</h2>
  4. <h2>{{reverseMessage}}</h2>
  5. </template>
  1. computed: {
  2. // 定义了一个计算属性叫fullname
  3. fullName() {
  4. return this.firstName + " " + this.lastName;
  5. },
  6. result() {
  7. return this.score >= 60 ? "及格": "不及格";
  8. },
  9. reverseMessage() {
  10. return this.message.split(" ").reverse().join(" ");
  11. }
  12. }

==========================

和方法的(methods)的区别

1、缓存

image.png

2、调用次数

多个插值,计算属性只会调用1次,而方法会调用多次,性能更低
image.png

==========================

计算属性内部方法getter和setter

每个计算属性内的函数内部,默认有2个方法:set,get,默认调用的是get方法

get方法:外部要读取这个计算属性的值时,调用这个方法里面的函数
set方法:外部要改变计算属性的值时,调用这个方法里面的函数
image.png
内部是这样运作的,当html使用到了计算属性时(如下图

{{addNum}}
):
1.先调用get方法
2.如果计算属性的值被其他改变了,就会调用set方法,set方法函数有一个参数n,n为这个计算属性获得的新值
3.然后再调用一次get方法

如下例子
1.先调用num,{{num}}显示0
2.再调用addNum,调用get方法,{{addNum}}显示1,
3.因为{{num}}发生了改变,因此{{num}}也会显示1
4.再运行一次addNum,由于计算属性的特性,只会运行一次,因此没变化
5.调用addAddNum,执行addAddNum的get方法,让addNum = 3
6.addNum 检测到值改变,因此把新的值3,传到了set方法里面的n,那么num变成11+3=14
7.然后再调用一次addNum的get方法,num变成15
8.num发生了改变,也显示15
image.png

调用的顺序,是和上面html从上到下执行有关的

  1. <template>
  2. <div id="app">
  3. <div>{{num}}</div>
  4. <div>{{addNum}}</div>
  5. <div>{{addNum}}</div>
  6. <div>{{addAddNum}}</div>
  7. </div>
  8. </template>
  9. <script>
  10. export default {
  11. data(){
  12. return {
  13. num:0
  14. }
  15. },
  16. computed:{
  17. addNum:{
  18. set:function(n){
  19. this.num = n+11
  20. },
  21. get:function(){
  22. return this.num+=1
  23. }
  24. },
  25. addAddNum:function(){
  26. this.addNum = 3
  27. }
  28. }
  29. };
  30. </script>

源码如何实现?

image.png

Vue 3写法

image.png

例子:
1、比如监听价格变量,我每次都想给这个变量加一个¥的符号,就可以通过计算属性返回加上符号的变量。这样不管价格怎么变,新变量都是加上符号的。

下面例子是Vue Cli 或者 Vite 等环境下用写组件的方法编写

  1. <template>
  2. <div>数值:{{money}}</div>
  3. <div>价格:{{price}}</div>
  4. <button @click="changeMoney">数值+1</button>
  5. <button @click="changePrice">重置价格</button>
  6. </template>
  7. <script>
  8. import { computed, ref } from "vue";
  9. export default {
  10. setup() {
  11. let money = ref(12);
  12. // 1、简单写法(只使用getter函数)
  13. // let price = computed(() => return `¥ ${money.value}`) // 返回的本质上是ref对象
  14. // 2、复杂写法(使用getter和setter函数)
  15. let price = computed({ //监听一个变量money,这个变量变化时,执行get方法进行新的操作,操作后的值赋值给price变量
  16. get: () => {
  17. return `¥ ${money.value}`;
  18. },
  19. set: (newValue) => { // price 变量的值被直接改变时,调用set方法,用的比较少
  20. return money.value = newValue; //这里例子,有人改变我的price,我会去同时影响源变量money,然后重新调用我的get方法加上¥符号
  21. },
  22. });
  23. const changeMoney = () => { // 改变监听的变量money,调用计算属性的get方法
  24. money.value += 1;
  25. };
  26. const changePrice = () => { // 改变price,调用计算属性的set方法
  27. price.value = 0;
  28. };
  29. return { money, price, changeMoney,changePrice };
  30. },
  31. };
  32. </script>
  33. <style>
  34. </style>