【vue3.0】15.0 Composition API(三)——计算属性computed、监听器watch

Composition API的计算属性computed

传统的计算属性不做介绍。
如下代码:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>lesson 38</title>
        <script src="https://unpkg.com/vue@next"></script>
    </head>
    <body>
        <div id="root"></div>
    </body>
    <script>
        // computed 计算属性
        const app = Vue.createApp({
            setup() {
                const { ref } = Vue;
                const count = ref(0);
                const handleClick = () => {
                    count.value += 1;
                };
                return { count,handleClick };
            },
            template: `
      <div>
        <span @click="handleClick">{{count}}</span>
      </div>
    `
        });

        const vm = app.mount('#root');
    </script>
</html>

最基础的计数器。

设计另一个数据,在第一个计数器的基础上加5:

<script>
        // computed 计算属性
        const app = Vue.createApp({
            setup() {
                const { ref } = Vue;
                const count = ref(0);
                const handleClick = () => {
                    count.value += 1;
                };
                
                //computed接受一个回调
                //计算一个加5的方法
                let countAddFive = computed(() => {
                    return count.value+5;
                });
                return { count, handleClick ,countAddFive};
            },
            template: `
      <div>
        <span @click="handleClick">{{count}}</span> -- {{countAddFive}}
      </div>
    `
        });

        const vm = app.mount('#root');
    </script>

这就是计算属性在 Composition API中的使用方法。

计算属性也可写成更复杂的内容:

<script>
        // computed 计算属性
        const app = Vue.createApp({
            setup() {
                const { ref } = Vue;
                const count = ref(0);
                const handleClick = () => {
                    count.value += 1;
                };
                
                //computed接受一个回调
                //计算一个加5的方法
                let countAddFive = computed(() => {
                    get: () => {
                      return count.value + 5;
                    },
                    
                });
                return { count, handleClick ,countAddFive};
            },
            template: `
      <div>
        <span @click="handleClick">{{count}}</span> -- {{countAddFive}}
      </div>
    `
        });

        const vm = app.mount('#root');
    </script>

这个效果等同于上面的简写方法。

<script>
        // computed 计算属性
        const app = Vue.createApp({
            setup() {
                const { ref } = Vue;
                const count = ref(0);
                const handleClick = () => {
                    count.value += 1;
                };
                
                //computed接受一个回调
                //计算一个加5的方法
                let countAddFive = computed(() => {
                    get: () => {
                      return count.value + 5;
                    },
                    set: () => {
                     count.value = 10;
                    }
                });
                
                setTimeout(() => {
                    //之所以要.value是因为其是被ref包裹的
                  countAddFive.value = 100;//当去修改的时候,会走set函数
                }, 3000)
                return { count, handleClick ,countAddFive};
            },
            template: `
      <div>
        <span @click="handleClick">{{count}}</span> -- {{countAddFive}}
      </div>
    `
        });

        const vm = app.mount('#root');
    </script>

3秒时候会修改count的值,由由于计算属性去读值会调用get方法,所以3秒之后会变为10--15
如果想要countAddFive的参数真正发挥作用,可以如下修改代码:

<script>
        // computed 计算属性
        const app = Vue.createApp({
            setup() {
                const { ref } = Vue;
                const count = ref(0);
                const handleClick = () => {
                    count.value += 1;
                };
                
                //computed接受一个回调
                //计算一个加5的方法
                let countAddFive = computed(() => {
                    get: () => {
                      return count.value + 5;
                    },
                    set: (param) => {
                     count.value = param - 5;
                    }
                });
                
                setTimeout(() => {
                    //之所以要.value是因为其是被ref包裹的
                  countAddFive.value = 100;//当去修改的时候,会走set函数
                }, 3000)
                return { count, handleClick ,countAddFive};
            },
            template: `
      <div>
        <span @click="handleClick">{{count}}</span> -- {{countAddFive}}
      </div>
    `
        });

        const vm = app.mount('#root');
    </script>

当然,以上可以再复杂一些:

<script>
  // computed 计算属性
  const app = Vue.createApp({
    setup() {
      const { reactive, computed } = Vue;
      const countObj = reactive({ count: 0});
      const handleClick = () => {
        countObj.count += 1;
      }
      let countAddFive = computed({
        get: () => {
          return countObj.count + 5;
        },
        set: (param) => {
          countObj.count = param - 5;
        }
      })

      setTimeout(() => {
        countAddFive.value = 100;
      }, 3000)

      return { countObj, countAddFive, handleClick }
    },
    template: `
      <div>
        <span @click="handleClick">{{countObj.count}}</span> -- {{countAddFive}}
      </div>
    `,
  });
  
  const vm = app.mount('#root');
</script>

监听器watch

初始代码如下:

<script>
        // watch 侦听器
        // watchEffect 侦听器,偏向于 effect
        const app = Vue.createApp({
            setup() {
                const { ref } = Vue;
                const name = ref('dell',);
                return { name };
            },
            template: `
      <div>
        <div>
          Name: <input v-model="name"> 
        </div>
        <div>
          Name is {{name}}
        </div>
      </div>
    `
        });

        const vm = app.mount('#root');
    </script>

上面的输入框内容变化,下面的显示内容也会跟着变。
这里我们用watch实现:

<script>
        // watch 侦听器
        // watchEffect 侦听器,偏向于 effect
        const app = Vue.createApp({
            setup() {
                const { ref, watch } = Vue;
                const name = ref('dell');

                // 具备一定的惰性 lazy
                // 回调函数的参数可以拿到原始和当前值
                // 可以侦听多个数据的变化,用一个侦听器承载
                watch(name, (newValue,oldValue) => {});

                return { name };
            },
            template: `
      <div>
        <div>
          Name: <input v-model="name"> 
        </div>
        <div>
          Name is {{name}}
        </div>
      </div>
    `
        });

        const vm = app.mount('#root');
    </script>

为了达到接下来的演示目的,现在把基础数据类型变为对象:

<script>
        // watch 侦听器
        // watchEffect 侦听器,偏向于 effect
        const app = Vue.createApp({
            setup() {
                const { reactive, watch, toRefs } = Vue;
                const nameObj = reactive({
                    name: 'dell'
                });

                // 具备一定的惰性 lazy
                // 回调函数的参数可以拿到原始和当前值
                // 可以侦听多个数据的变化,用一个侦听器承载
                //监听一个对象的某一个属性,需要将参数变成一个函数
                watch(()=>nameObj.name, (newValue, oldValue) => {});

                const { name } = toRefs(nameObj);
                return { name };
            },
            template: `
      <div>
        <div>
          Name: <input v-model="name"> 
        </div>
        <div>
          Name is {{name}}
        </div>
      </div>
    `
        });

        const vm = app.mount('#root');
    </script>

修改代码:

<script>
        // watch 侦听器
        // watchEffect 侦听器,偏向于 effect
        const app = Vue.createApp({
            setup() {
                const { reactive, watch, toRefs } = Vue;
                const nameObj = reactive({
                    name: 'dell',
                    englishName: 'lee'
                });

                // 具备一定的惰性 lazy
                // 回调函数的参数可以拿到原始和当前值
                // 可以侦听多个数据的变化,用一个侦听器承载
                //监听一个对象的某一个属性,需要将参数变成一个函数
                watch(
                [
                    () => nameObj.name, 
                    () => nameObj.englishName
                    ], 
                ([newName, newEng], 
                [oldName, oldEng]) => {
                    console.log('watch', curName, prevName, '---', curEng, preEng);
                });

                const { name } = toRefs(nameObj);
                return { name };
            },
            template: `
      <div>
        <div>
          Name: <input v-model="name"> 
        </div>
        <div>
          Name is {{name}}
        </div>
        <div>
          EnglishName: <input v-model="englishName"> 
        </div>
        <div>
          EnglishName is {{englishName}}
        </div>
      </div>
    `
        });

        const vm = app.mount('#root');
    </script>

以上就是多参数监听。

image.png

watchEffect

watchEffect语法和watch一样。watchEffect写法没有watch那么麻烦,只需要写一个回调函数即可。

<script>
        // watch 侦听器
        // watchEffect 侦听器,偏向于 effect
        const app = Vue.createApp({
            setup() {
                const { reactive, watch, toRefs ,watchEffect} = Vue;
                const nameObj = reactive({
                    name: 'dell',
                    englishName: 'lee'
                });

                //watchEffect是立即执行的,没有惰性。immediate
                //watchEffect会自动检测内部的代码
                watchEffect(()=>{
                    console.log('aaa');
                    
                })

                const { name } = toRefs(nameObj);
                return { name };
            },
            template: `
      <div>
        <div>
          Name: <input v-model="name"> 
        </div>
        <div>
          Name is {{name}}
        </div>
        <div>
          EnglishName: <input v-model="englishName"> 
        </div>
        <div>
          EnglishName is {{englishName}}
        </div>
      </div>
    `
        });

        const vm = app.mount('#root');
    </script>

以上代码aaa只会执行一次,但是修改如下之后,每次修改都会执行。

......
                watchEffect(()=>{
                    console.log('watchEffect', curName, prevName, '---', curEng, preEng);
                })
......
  • watchEffect是立即执行的,没有惰性。immediate
  • watchEffect会自动检测内部的代码,不需要传递任何需要监听的内容
  • watchEffect无法获取旧的值,只能获取最新的值

接下来写一个功能:2秒之后监听器取消,不再监听:

<script>
        // watch 侦听器
        // watchEffect 侦听器,偏向于 effect
        const app = Vue.createApp({
            setup() {
                const { reactive, watch, toRefs ,watchEffect} = Vue;
                const nameObj = reactive({
                    name: 'dell',
                    englishName: 'lee'
                });

                // 具备一定的惰性 lazy
                // 回调函数的参数可以拿到原始和当前值
                // 可以侦听多个数据的变化,用一个侦听器承载
                //监听一个对象的某一个属性,需要将参数变成一个函数
                // watch(
                // [
                //  () => nameObj.name, 
                //  () => nameObj.englishName
                //  ], 
                // ([newName, newEng], 
                // [oldName, oldEng]) => {
                //  console.log('watch', curName, prevName, '---', curEng, preEng);
                
                //watchEffect是立即执行的,没有惰性。immediate
                //watchEffect会自动检测内部的代码,不需要传递任何需要监听的内容
                //watchEffect无法获取旧的值,只能获取最新的值
                const stop = watchEffect(() => {
                  console.log(nameObj.name);
                  console.log(nameObj.englishName);
                  setTimeout(() => {
                    stop();
                  }, 5000)
                })

                const { name } = toRefs(nameObj);
                return { name };
            },
            template: `
      <div>
        <div>
          Name: <input v-model="name"> 
        </div>
        <div>
          Name is {{name}}
        </div>
        <div>
          EnglishName: <input v-model="englishName"> 
        </div>
        <div>
          EnglishName is {{englishName}}
        </div>
      </div>
    `
        });

        const vm = app.mount('#root');
    </script>

watch也有这样的使用方法。

有没有办法把watch变成非惰性的?可以:

......

                // 具备一定的惰性 lazy
                // 回调函数的参数可以拿到原始和当前值
                // 可以侦听多个数据的变化,用一个侦听器承载
                //监听一个对象的某一个属性,需要将参数变成一个函数
                watch(
                [
                    () => nameObj.name, 
                    () => nameObj.englishName
                    ], 
                ([newName, newEng], 
                [oldName, oldEng]) => {
                    console.log('watch', curName, prevName, '---', curEng, preEng);
                },{
                    //这里可以传很多高级的配置
                     immediate: true //非惰性:立即执行
                });
......
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值