• Vue3 —— 常用 Composition API(一)(computed函数、watch函数、watchEffect函数、生命周期钩子)


    系列文章目录

    Vue3 —— 创建 Vue3.0 工程

    Vue3 —— 常用 Composition API(零)(setup函数、ref函数、reactive函数、响应式、reactive对比ref)

    Vue3 —— 常用 Composition API(一)(computed函数、watch函数、watchEffect函数、生命周期钩子)

    Vue3 —— 常用 Composition API(二)(hook 函数、toRef 和 toRefs)

    Vue3 —— 其他 Composition API(shallowReactive、shallowRef、readonly、shallowReadonly、toRaw、markRaw…)

    Vue3 —— 新的组件及一些改变(Fragment、Teleport、Suspense、其他的改变)



    一、computed 函数

    1. 计算属性 — 简写(不考虑计算属性被修改的情况)

    1. 在 setup 中定义 person 对象,通过 reactive 设置成响应式
    2. 给 person 添加计算属性,名为 fullName,返回全名
    	<template>
    	  <div>
    	    <h3>一个人的信息</h3>
    	    姓:<input type="text" v-model="person.firstName" /><br />
    	    名:<input type="text" v-model="person.lastName" /><br />
    	    <span>全名:{{ person.fullName }}</span><br/>
    	  </div>
    	</template>
    	
    	<script>
    	import { reactive, computed } from "vue";
    	export default {
    	  name: "Demo",
    	  setup() {
    	    // 数据
    	    let person = reactive({
    	      firstName: "张",
    	      lastName: "三",
    	    });
    	    // 计算属性——简写(没有考虑计算属性被修改的情况)
    	    person.fullName = computed(()=>{
    	      return person.firstName + '-' + person.lastName
    	    })
    	
    	    // 返回一个对象
    	    return {
    	      person,
    	    };
    	  },
    	};
    	</script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    计算属性显示全名:

    在这里插入图片描述

    2. 计算属性 — 完整写法(考虑计算属性被修改的情况)

    1. 动态修改 input 框,响应式变化
    2. 完整写法,要在计算属性内配置 get 和 set
    3. get 里面是返回值,set 里面给对应属性赋值
    	<template>
    	  <div>
    	    <h3>一个人的信息</h3>
    	    姓:<input type="text" v-model="person.firstName" /><br />
    	    名:<input type="text" v-model="person.lastName" /><br />
    	    <span>全名:{{ person.fullName }}</span><br/>
    	    全名:<input type="text" v-model="person.fullName">
    	  </div>
    	</template>
    	
    	<script>
    	import { reactive, computed } from "vue";
    	export default {
    	  name: "Demo",
    	  setup() {
    	    // 数据
    	    let person = reactive({
    	      firstName: "张",
    	      lastName: "三",
    	    });
    	
    	    // 计算属性——完整写法(考虑读和写)
    	    person.fullName = computed({
    	      get(){
    	        return person.firstName + '-' + person.lastName
    	      },
    	      set(value){
    	        const nameArr = value.split('-')
    	        person.firstName = nameArr[0]
    	        person.lastName = nameArr[1]
    	      }
    	    })
    	
    	    // 返回一个对象
    	    return {
    	      person,
    	    };
    	  },
    	};
    	</script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    效果如下:

    在这里插入图片描述

    二、watch 函数

    1. 监视 ref 所定义的一个响应式数据

    1. 第一个参数:监听的是谁
    2. 第二个参数:监视的回调
    3. 第三个参数:监视的配置 => 立即执行(页面一经加载就执行一次)
    	<template>
    	  <div>
    	    <h3>当前求和为:{{ sum }}</h3>
    	    <button @click="sum++">点我+1</button>
    	  </div>
    	</template>
    	
    	<script>
    	import { ref, watch } from "vue";
    	export default {
    	  name: "Demo",
    	  setup() {
    	    // 数据
    	    let sum = ref(0);
    	    
    	    // 情况一:监视ref所定义的一个响应式数据
    	    watch(sum, (newValue, oldValue) => {
    	      console.log("sum变了", newValue, oldValue);
    	    }, {immediate: true});
    	    
    	    // 返回一个对象
    	    return {
    	      sum,
    	    };
    	  },
    	};
    	</script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    监听 ref 所定义的一个响应式数据:

    在这里插入图片描述

    2. 监视 ref 所定义的多个响应式数据

    1. 监视多个响应式数据:sum 和 msg
    2. sum 每次 +1,msg 每次多一个 !
    3. 监听多个数据:用 [] 括起来
    	<template>
    	  <div>
    	    <h3>当前求和为:{{ sum }}</h3>
    	    <button @click="sum++">点我+1</button>
    	    <hr/>
    	    <h3>当前的信息为:{{ msg }}</h3>
    	    <button @click="msg+='!'">修改信息</button>
    	  </div>
    	</template>
    	
    	<script>
    	import { ref, watch } from "vue";
    	export default {
    	  name: "Demo",
    	  setup() {
    	    // 数据
    	    let sum = ref(0);
    	    let msg = ref('你好啊')
    	
    	    // 情况二:监视ref所定义的多个响应式数据
    	    watch([sum, msg], (newValue, oldValue)=>{
    	      console.log('sum或msg变了', newValue, oldValue);
    	    })
    	    
    	    // 返回一个对象
    	    return {
    	      sum,
    	      msg,
    	    };
    	  },
    	};
    	</script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    按钮分别点击两次:

    在这里插入图片描述

    3. 监视 reactive 所定义一个响应式数据的全部数据

    1. 监视 reactive 定义的响应式数据时:oldValue 无法正确获取
    2. 监视 reactive 定义的响应式数据时:强制开启了深度监视(deep 配置失效)
    	<template>
    	  <div>
    	    <h3>姓名:{{person.name}}</h3>
    	    <h3>年龄:{{person.age}}</h3>
    	    <button @click="person.name+='~'">修改姓名</button>
    	    <button @click="person.age++">增长年龄</button>
    	  </div>
    	</template>
    	
    	<script>
    	import { reactive, watch } from "vue";
    	export default {
    	  name: "Demo",
    	  setup() {
    	    // 数据
    	    let person = reactive({
    	      name: '张三',
    	      age: 18,
    	    })
    	
    	    /* 
    	      情况三:监视reactive所定义一个的响应式数据的全部数据
    	        1.注意:此处无法正确的获取oldValue
    	        2.注意:强制开启了深度监视(即deep配置无效)
    	    */
    	    watch(person, (newValue, oldValue)=>{
    	      console.log('person变化了', newValue, oldValue);
    	    }, {deep: true})
    	
    	    // 返回一个对象
    	    return {
    	      person
    	    };
    	  },
    	};
    	</script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    都是显示的 newValue:

    在这里插入图片描述

    4. 监视 reactive 所定义一个响应式数据中的某个属性

    1. 要写成函数的形式 () => person.age
    	<template>
    	  <div>
    	    <h3>姓名:{{person.name}}</h3>
    	    <h3>年龄:{{person.age}}</h3>
    	    <button @click="person.name+='~'">修改姓名</button>
    	    <button @click="person.age++">增长年龄</button>
    	  </div>
    	</template>
    	
    	<script>
    	import { reactive, watch } from "vue";
    	export default {
    	  name: "Demo",
    	  setup() {
    	    // 数据
    	    let person = reactive({
    	      name: '张三',
    	      age: 18,
    	    })
    	
    	    // 情况四:监视reactive所定义一个响应式数据中的某个属性
    	    watch(() => person.age, (newValue, oldValue)=>{
    	      console.log('person的age变化了', newValue, oldValue);
    	    })
    	
    	    // 返回一个对象
    	    return {
    	      person
    	    };
    	  },
    	};
    	</script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    某个属性:oldValue 可以获取:

    在这里插入图片描述

    5. 监视 reactive 所定义一个的响应式数据中的某些属性

    1. [] 包裹起来,写成数组的形式
    2. 多个属性分别用函数形式表示
    	<template>
    	  <div>
    	    <h3>姓名:{{person.name}}</h3>
    	    <h3>年龄:{{person.age}}</h3>
    	    <button @click="person.name+='~'">修改姓名</button>
    	    <button @click="person.age++">增长年龄</button>
    	  </div>
    	</template>
    	
    	<script>
    	import { reactive, watch } from "vue";
    	export default {
    	  name: "Demo",
    	  setup() {
    	    // 数据
    	    let person = reactive({
    	      name: '张三',
    	      age: 18,
    	    })
    	
    	    // 情况五:监视reactive所定义一个的响应式数据中的某些属性
    	    watch([() => person.name, () => person.age], (newValue, oldValue) => {
    	      console.log('person的name或age变化了', newValue, oldValue);
    	    })
    	
    	    // 返回一个对象
    	    return {
    	      person
    	    };
    	  },
    	};
    	</script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    依次点击修改姓名,增长年龄:

    在这里插入图片描述

    6. 监视 reactive 定义的响应式数据中某个属性时:deep配置有效。

    1. 若设置 deep: false ,则控制台没有输出
    2. 监视 reactive 定义的响应式数据中某个属性时:deep配置有效。
    	<template>
    	  <div>
    	    <h3>姓名:{{person.name}}</h3>
    	    <h3>年龄:{{person.age}}</h3>
    	    <h3>薪资:{{person.job.j1.salary}}K</h3>
    	    <button @click="person.name+='~'">修改姓名</button>
    	    <button @click="person.age++">增长年龄</button>
    	    <button @click="person.job.j1.salary++">增加薪资</button>
    	  </div>
    	</template>
    	
    	<script>
    	import { reactive, watch } from "vue";
    	export default {
    	  name: "Demo",
    	  setup() {
    	    // 数据
    	    let person = reactive({
    	      name: '张三',
    	      age: 18,
    	      job: {
    	        j1:{
    	          salary: 20
    	        }
    	      }
    	    })
    	
    	    // 特殊情况:监视reactive定义的响应式数据中某个属性时:deep配置有效。
    	    watch(() => person.job, (newValue, oldValue) => {
    	      console.log('person的job变化了', newValue, oldValue);
    	    }, {deep: false})
    	
    	
    	    // 返回一个对象
    	    return {
    	      person
    	    };
    	  },
    	};
    	</script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    开启深度监视:

    在这里插入图片描述

    三、watchEffect 函数

    1. 对比 watch 和 watchEffect

    1. watch 的套路:既要指明监视的属性,也要指明监视的回调
    2. watchEffect 的套路:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性

    2. watchEffect 类似于 computed

    1. 但 computed 注重的计算出来的值(回调函数的返回值),所以必须要写返回值
    2. 而 watchEffect 更注重的是过程(回调函数的函数体),所以不用写返回值

    当点击 点我+1增加薪资 时会被监视:

    	<template>
    	  <div>
    	    <h3>当前求和为:{{ sum }}</h3>
    	    <button @click="sum++">点我+1</button>
    	    <hr/>
    	    <h3>薪资:{{person.job.j1.salary}}K</h3>
    	    <button @click="person.job.j1.salary++">增加薪资</button>
    	  </div>
    	</template>
    	
    	<script>
    	import { ref, reactive, watchEffect } from "vue";
    	export default {
    	  name: "Demo",
    	  setup() {
    	    // 数据
    	    let sum = ref(0);
    	    let person = reactive({
    	      job: {
    	        j1:{
    	          salary: 20
    	        }
    	      }
    	    })
    	
    	    watchEffect(()=>{
    	      const x1 = sum.value
    	      const x2 = person.job.j1.salary
    	      console.log('watchEffect所指定的回调执行了', x1, x2);
    	    })
    	
    	    // 返回一个对象
    	    return {
    	      sum,
    	      msg,
    	      person
    	    };
    	  },
    	};
    	</script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    第一个按钮点击一次,第二个按钮点击两次:

    在这里插入图片描述

    四、生命周期钩子

    1. 官方图解

    在这里插入图片描述

    2. 通过配置项的形式使用生命周期钩子

    1. setup 就是一个配置项,通过配置项的形式使用钩子
    2. 下面对生命周期钩子进行简单测试

    App.vue

    	<template>
    	  <div>
    	    <button @click="isShowDemo = !isShowDemo">切换隐藏/显示</button>
    	    <Demo v-if="isShowDemo" />
    	  </div>
    	</template>
    	
    	<script>
    	import { ref } from "vue";
    	import Demo from "./components/Demo.vue";
    	export default {
    	  name: "App",
    	  components: { Demo },
    	  setup() {
    	    let isShowDemo = ref(true);
    	    return { isShowDemo };
    	  },
    	  
    	};
    	</script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    Demo.vue

    	<template>
    	  <div>
    	    <h3>当前求和为:{{ sum }}</h3>
    	    <button @click="sum++">点我+1</button>
    	  </div>
    	</template>
    	
    	<script>
    	import { ref } from "vue";
    	export default {
    	  name: "Demo",
    	  setup() {
    	    // 数据
    	    let sum = ref(0);
    		
    	    // 返回一个对象
    	    return { sum };
    	  },
    	
    	  // 通过配置项的形式使用生命周期钩子
    	  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---');
    	  }
    	};
    	</script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    页面一加载:

    在这里插入图片描述

    点击求和:

    在这里插入图片描述

    点击切换/隐藏显示:

    在这里插入图片描述

    3. 通过组合式API的形式去使用生命周期钩子

    1. 把生命周期钩子写入 setup 配置项里面
    	<template>
    	  <div>
    	    <h3>当前求和为:{{ sum }}</h3>
    	    <button @click="sum++">点我+1</button>
    	  </div>
    	</template>
    	
    	<script>
    	import { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from "vue";
    	export default {
    	  name: "Demo",
    	  setup() {
    	    // 数据
    	    let sum = ref(0);
    	
    	    // 通过组合式API的形式去使用生命周期钩子
    	    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 };
    	  },
    	};
    	</script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    不积跬步无以至千里 不积小流无以成江海

    点个关注不迷路,持续更新中…

  • 相关阅读:
    【微服务 从0开始 】Spring Cloud 配置文件
    Java扫描区块链的工具包|Java扫块|监听token转账
    pytorch环境搭建到pycharm项目映射配置(成功后回顾性记录/自用)
    01_SHELL编程之变量定义(一)
    sgu 176 Flow construction (有汇源有上下界的最小流)
    安全保障基于软件全生命周期-Istio的认证机制
    基于JavaSwing开发学生信息管理系统(SQLServer数据库版本) 毕业设计 课程设计 大作业
    目标检测——UCF50动作识别数据集
    使用 Bun 快速搭建一个 http 服务
    技术人的面试求职套路
  • 原文地址:https://blog.csdn.net/qq_45902692/article/details/125907607