vue3——computed、watch、watchEffect、生命周期、hooks、toRef

vue3.x

computed函数

与vue2中computed配置功能一致

import { computed } from "vue";
setup(){
//简写
	let test = computed(()=>{
		return 1+1
	})
//完整
	let demo =computed({
		get(){
			return 1+1
		},
		set(value){
			value+1
		}
	})
}
watch函数

与Vue2.x中的watch配置功能一致

监视的是属性(结构),而不是属性值,所以监视ref定义的数据,不用加.value

两个‘小坑’:

​ 1. 监视reactive定义的响应式数据时:oldValue无法正确获取,强制开启了深度监视(deep:false配置失效)

​ 2.监视reactive定义的响应式数据中某个属性(对象)时,deep配置有效

<template>
  <div>
    <h2>求和结果:{{ sum }}</h2>
    <button @click="sum++">+1</button>
    <hr />
    <p>信息:{{ msg }}</p>
    <button @click="msg += '!'">hi</button>
    <hr />
    <p>姓名:{{ obj.name }}</p>
    <p>年龄:{{ obj.age }}</p>
    <p>工作:{{ obj.job.job1.name }}</p>
    <p>薪资:{{ obj.job.job1.salary }}K</p>
    <button @click="obj.name += '-'">修改姓名</button>
    <button @click="obj.age++">修改年龄</button>
    <button @click="obj.job.job1.salary++">加薪</button>
  </div>
</template>

<script>
import { ref, watch, reactive } from "vue";
export default {
  // vue2的watch,vue3也可以用
  /*  watch: {
    //   简写
    // sum(newVal, oldVal) {
    //   console.log("sum的值改变了");
    // },
    // 完整——可以配置属性
    sum: {
      // 立即监听
      immediate: true,
      // 深度监视
      deep: true,
      handler(newVal, oldVal) {
        //   console.log("sum的值改变了");
      },
    },
  }, */
  setup() {
    //   sum是基本数据类型,所以用ref
    let sum = ref(0);
    let msg = ref("hello");
    let obj = reactive({
      name: "张三",
      age: 22,
      job: {
        job1: {
          name: "web工程师",
          salary: 20,
        },
      },
    });
    // 情况一:监视ref所定义的一个响应式数据
    /* watch(sum, (newVal, oldVal) => {
      console.log("sum的值改变了");
    },{immediate:true}); */
    // 情况二:监视ref所定义的多个响应式数据
    /*  watch([sum, msg], (newVal, oldVal) => {
      console.log("值改变了");
    },{immediate:true}); */
    // 情况三:监视reactive所定义的一个响应式数据的全部属性,
    // 注意:1.此处无法正确的获取oldVal;2.强制开启了深度监视(deep:false配置无效)
    /* watch(obj, (newVal, oldVal) => {
      console.log("sum的值改变了");
    },{deep:false}); */
    // 情况四:监视reactive所定义的一个响应式数据的某个属性
    /* watch(()=>obj.age, (newVal, oldVal) => {
      console.log("sum的值改变了");
    }); */
    // 情况五:监视reactive所定义的一个响应式数据的某些属性
    /* watch([()=>obj.age,()=>obj.name], (newVal, oldVal) => {
      console.log("sum的值改变了");
    });  */
    // 特殊情况
    watch(
      () => obj.job,
      (newVal, oldVal) => {
        console.log("job里面的值改变了");
      },
      { deep: true }//由于此处监视的是reactive所定义的对象中的某个属性,所以deep配置有效
    );
    return { sum, msg, obj };
  },
};
</script>

<style>
</style>
监视ref定义的数据的问题
<template>
  <div>
    <h2>求和结果:{{ sum }}</h2>
    <button @click="sum++">+1</button>
    <hr />
    <p>信息:{{ msg }}</p>
    <button @click="msg += '!'">hi</button>
    <hr />
    <p>姓名:{{ obj.name }}</p>
    <p>年龄:{{ obj.age }}</p>
    <p>工作:{{ obj.job.job1.name }}</p>
    <p>薪资:{{ obj.job.job1.salary }}K</p>
    <button @click="obj.name += '-'">修改姓名</button>
    <button @click="obj.age++">修改年龄</button>
    <button @click="obj.job.job1.salary++">加薪</button>
  </div>
</template>

<script>
import { ref, watch, reactive } from "vue";
export default {
  setup() {
    //   sum是基本数据类型,所以用ref
    let sum = ref(0);
    let msg = ref("hello");
    let obj = ref({
      name: "张三",
      age: 22,
      job: {
        job1: {
          name: "web工程师",
          salary: 20,
        },
      },
    });
    // sum是ref定义的数据,是RefImpl对象
    watch(sum, (newVal, oldVal) => {
      console.log("监视到sum的值改变了,");
    });
    /* watch(obj, (newVal, oldVal) => {
      console.log("监视到obj内的值改变了,");
    }); 监视不到*/
    // obj是ref定义的数据,是RefImpl对象,但是obj里面的value是reactive定义的,是Proxy对象
    // 方式一:
    /* watch(obj.value, (newVal, oldVal) => {
      console.log("监视到obj内的值改变了,");
    }); */
    watch(
      obj,
      (newVal, oldVal) => {
        console.log("监视到obj内的值改变了,");
      },
      { deep: true }
    );
    return {
      sum,
      msg,
      obj,
    };
  },
};
</script>

<style>
</style>

watchEffect函数

watch的套路是:既要指明监视的属性,也要指明监视的回调

watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性

watchEffect有点像computed:

​ 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值

​ 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值

//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调
watchEffect(()=>{
        const x1=sum.value;
        const x2=obj.job.job1.salary
        console.log('watchEffect所指定的回调执行了');
    })

生命周期

<template>
  <div>
    <h2>求和结果:{{ sum }}</h2>
    <button @click="sum++">+1</button>
  </div>
</template>

<script>
// 组合式API
import {
  ref,
  onBeforeMount,
  onMounted,
  onBeforeUpdate,
  onUpdated,
  onBeforeUnmount,
  onUnmounted,
} from "vue";
export default {
  // setup先执行再到beforeCreate
  // 在setup里面没有beforeCreate和created这两个组合API
  setup() {
    let sum = ref(0);
    console.log("setup");

    onBeforeMount(() => {
      console.log("onBeforeMount");
    }),
      onMounted(() => {
        console.log("onMounted");
      }),
      onBeforeUpdate(() => {
        console.log("onBeforeUpdate");
      }),
      onUpdated(() => {
        console.log("onUpdated");
      }),
      onBeforeUnmount(() => {
        console.log("onBeforeUnmount");
      }),
      onUnmounted(() => {
        console.log("onUnmounted");
      });
    return {
      sum,
    };
  },
  // 若setuo里面的组合式API的生命周期钩子时期比配置项的生命周期钩子快一点
  // 通过配置项的形式使用生命周期钩子
  //#region
  beforeCreate() {
    console.log("beforeCreate");
  },
  created() {
    console.log("created");
  },
  beforeMount() {
    console.log("beforeMount");
  },
  mounted() {
    console.log("mounted");
  },
  beforeUpdate() {
    console.log("beforeUpdate");
  },
  updated() {
    console.log("updated");
  },
  beforeUnmount() {
    console.log("beforeUnmount");
  },
  unmounted() {
    console.log("unmounted");
  },
  //#endregion
};
</script>

<style>
</style>

自定义hooks函数

什么是hooks?:本质是一个函数,把setup函数中使用的CompositionApi 进行了封装

类似于Vue2.x中的mixin

自定义hook的优势:复用代码,让setup中的逻辑更清楚易懂

toRef

作用:创建一个ref对象,其value值指向另一个对象中的某个属性

语法:

    const newName = toRef(obj,'name')

应用:要将响应式对象中的某个属性单独提供给外部使用时,还不想丢失响应式,就可以使用toRef

扩展:toRefs与toRef功能一致,但可以批量创建多个ref对象,语法:toRefs(obj),返回的是一个对象,需要定义一个变量接收,或者在return直接使用**…toRefs(obj)**

<template>
  <div>
    <p>{{obj}}</p>
    <p>姓名:{{ name }}</p>
    <p>年龄:{{ age }}</p>
    <p>工作:{{ job.job1.name }}</p>
    <p>薪资:{{ job.job1.salary }}K</p>
    <button @click="name += '-'">修改姓名</button>
    <button @click="age++">修改年龄</button>
    <button @click="job.job1.salary++">加薪</button>
  </div>
</template>

<script>
import { reactive, toRef, toRefs } from "vue";
export default {
  setup() {
    let obj = reactive({
      name: "张三",
      age: 22,
      job: {
        job1: {
          name: "web工程师",
          salary: 20,
        },
      },
    });
    // 页面可以显示相关的信息,但是修改不了,不是响应式数据
    /* return {
      // obj,
      name:obj.name,//'张三
      age:obj.age,//22
      job:obj.job.job1.name,//'web工程师'
      salary:obj.job.job1.salary//20
    }; */
    return {
      obj,
      // 下面几个属性常用
      // toRef只能处理一个属性
      /* name:toRef(obj,'name'),
      age:toRef(obj,'age'),
      jobName:toRef(obj.job.job1,'name'),
      salary:toRef(obj.job.job1,'salary') */
      // toRefs可以处理多个属性,返回一个对象,所以需要接收
      // ...:在一个对象使用...展开另外一个对象,只能展开到该对象的第一层,深层的展开不了
      ...toRefs(obj)
    }
  },
};
</script>

<style>
</style>
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值