当前位置: 首页 > java >正文

VUE3 学习笔记2 computed、watch、生命周期、hooks、其他组合式API

computed 计算属性

在vue3中,虽然也能写vue2的computed,但还是更推荐使用vue3语法的computed。

在Vue3中,计算属性是组合式API,要想使用computed,需要先对computed进行引入:

import { computed } from 'vue'

computed是一个函数。它的参数接收一个函数,这个函数可以是普通函数,也可以是箭头函数,由于vue3中没有this,所以无需关注函数类型对this指向的影响。这个函数就是计算的方法函数。

<template>{{ totName }}
</template><script>import { computed } from 'vue'export default{setup(){let name = 'dog'let age = 12let totName = computed( ()=>{return name + age;})return{totName,}}}
</script>

但是通过这种方式定义的计算属性,是只读的,无法对属性进行修改。如果计算属性同时需要读取和修改,要通过下面这种形式:

传入computed的参数是一个对象,在对象中配置get和set。

<template>{{ totName }}<button @click=change>click</button>
</template><script>import { ref,computed } from 'vue'export default{setup(){let name = ref('dog')let age = ref(12)let totName = computed( {get(){return name.value + age.value;},set(value){name.value = value[0];age.value = value[1];}})function change(){totName.value = ['cat',10];}return{totName,change}}}
</script>

watch

在vue3中,watch也是组合式API,也需要引入:

import { watch } from 'vue'

与其他组合式API一样,其实组合式API就是Vue3提供的一些函数,因此watch也是一个函数。

watch的第一个参数是需要监视的数据,第二个参数类似handler函数,当要监视的数据改变时,调用这个函数,函数提供两个参数 监视数据新的值,监视数据旧的值。第三个参数是配置对象,可以用于配置immediate和deep。

在vue2中,watch配置项只有一个,但是在vue3中,可以使用多次watch函数。

如果想用vue3监控多个数据的改变,可以写多个watch函数,也可以把第一个参数写成数组,数组中的每个元素都是想要监视的数据。第二个参数中,newValue和oldValue也是数组的形式,数组中第n个元素对应第n个被监视的数据的newValue和oldValue。

要注意:

如果watch监视的数据是一个对象,当修改了对象中某个属性的数据,在watch的回调函数中,newValue和oldValue值是一样的。也就是说,通过ref定义的普通类型响应式数据,用watch进行监测,new和old的值才是正确的。如果通过ref或reactive创建的响应式对象,在watch中无法获取正确的new和old值。如果是ref定义的对象,需要在监测对象里写.value语法,且和reactive一样,newValue和oldValue都是newValue。这个问题目前无法解决,但是,由于在开发中,需要oldValue的情况并不多,如果确实需要oldValue,要把监测的数据定义成普通类型的数据。

除此之外,如果监测的数据是用reactive创建的响应式,即使对象的层级较多,不设置deep:true,也能对对象进行深度监测。如果不需要深度监测,需要设置deep:false。

如果只想监测对象中某个具体的属性,而不是整个对象中所有属性,在第一个参数上写对象.属性,用这种语法,监测是无法生效的。watch只能监测ref、reactive。如果想要监测对象上某个具体的属性,第一个参数应该是一个函数,函数的返回值是对象.属性,watch才能够正常监测。而且,这时候newValue和oldValue是正确的数值。

如果想监视对象中的某些属性,需要写一个数组,数组中每个元素都是函数,函数的返回值是需要监视的数据,且数据是普通数据类型。通过这种语法,可以正确获取newValue和oldValue。

但如果要监测的是对象中的某个属性,这个属性还是一个对象,此时需要开启deep:true,否则无法监测到数据的变更。

也就是说,对于watch,根据监测对象的不同,会产生以下现象:

1.如果监测整个对象,默认强制开启deep:true。

2.如果监测函数中的某个属性,需要以函数返回值的形式返回这个属性。

3.如果想要正确监测对象中的对象属性,需要打开deep:true设置。

watchEffect

watchEffect是一个函数,使用之前需要先引入:

import { watchEffect } from 'vue'

watchEffect的参数是一个回调函数,它会监测内部的回调函数涉及了哪些变量,当涉及的变量数值发生变化时,回调函数就会被触发。watchEffect初始就会被执行一次,然后当内部涉及的数据变化时也会执行。

watchEffect和watch和computed:

watchEffect和watch都是用于监测数据,在数据发生变化时调用回调函数,但是不同的是,watch既要知名监视的属性,也要指明回调。watchEffect不需要指明监视的属性,只需要指明回调函数,在回调函数中用到哪个属性,就会监视涉及的属性。

watchEffect和computed:watchEffect回调函数的触发逻辑和computed类似,都是初始时会执行一次,然后当内部依赖的数据发生变化时,执行一次。但computed是计算属性,需要返回计算值。watchEffect是监视属性,它关注过程,无需返回值。

Vue3生命周期

在vue3中,销毁组件时,触发的是beforeUnmount和unmounted钩子,而没有beforeDestroy和destroyed钩子。在vue3中,称为卸载。

对于vue2来说,如果调用new Vue时,没有传递el,那么会走到created钩子之后,才会判断el是否配置了。但在vue3中,在一开始,创建了app实例之后,需要进行app.mount,然后才进入生命周期。

在vue3中,当组件卸载时,会触发beforeUnmount钩子和unmount钩子。vue3把生命周期分为挂载->卸载流程。除此之外,vue3生命周期的各种概念和逻辑都跟vue2一样。

但是,vue3中,如果想通过setup组合式API去使用生命周期钩子,钩子的名称会发生变化:

beforeCreate -> setup()

created -> setup()

在vue3中,并没有给beforeCreate和created钩子提供API,但可以把setup看做beforeCreate和created。

beforeMount -> onBeforeMount

mounted -> onMounted

beforeUpdate -> onBeforeUpdate

updated -> onUpdated

beforeUnmount -> onBeforeUnmount

unmounted -> onUnmounted

<script>import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue'export default{setup(){onBeforeMount(()=>{console.log('onbeforeMount')})onMounted(...)onBeforeUpdate(...)onUpdated(...)onBeforeUnmount(...)onUnmounted(...)}}
</script>

要使用setup组合式API,都需要先进行引入,他们都是函数。

这些函数都接收一个函数作为参数,在对应的时机,这个参数函数就会被调用。

在vue3中,由于可以同时定义生命周期配置项,以及setup中的组合式API生命钩子,有时候会产生令人难以理解的执行顺序,如果同时定义了配置项和组合式,实际上,在挂载时,setup()函数是最先被执行的->beforeCreate->created->onBeforeMount->beforeMount->onMounted->mounted。更新时的执行顺序是onBeforeUpdate->beforeUpdate->onUpdated->updated。卸载时的执行顺序是onBeforeUpdate->beforeUpdate->onupdated->updated。也就是说,组合式API生命周期的执行时机比配置项快一些。

但是一般不推荐同时使用生命周期配置项和setup组合式API生命钩子。

hooks

hook也是一个函数,它把setup函数中使用的组合式API进行了封装。

原始功能:

<template><h2>{{ num }}</h2><button @click=change>click</button>
</template><script>import { onMounted, ref } from 'vue'export default{setup(){let num = ref(0);function change(){num.value++;}onMounted(()=>{num.value = 5;})return{num,change,}}}
</script>

对于某个功能,可以把这个功能涉及的数据、方法、生命周期逻辑抽出来,抽成一个函数,把这个函数单独放在js中,函数返回功能需要的数据或方法,并对外暴露。当vue文件引入这个js时,就可以复用这个功能(因为vue文件获取了这个函数,函数里包含了使用功能需要的所有代码逻辑)。

一般这个js文件就是一个hook的思想,它一般放在src下的hooks文件里。

hook类似于vue2的mixin。通过自定义hook,可以复用代码,让setup中的逻辑更清晰。

组合式API

除了前面学到的组合式API,vue3中还具有很多其他的API,这里先学习其中一部分剩余API。

toRef

toRef用于创建一个ref对象,它的value值指向另一个对象中的某个属性。

有时候,希望拿一个变量存储对象中的属性,而且希望对象中的属性改变时,变量中存储的属性也发生改变,当变量中数据改变时,有时候也希望反馈到对象上。

直接通过变量存储对象属性时,无法达成这种效果。

但toRef可以把一个并非ref响应式的数据变成ref。toRef接收两个参数,第一个参数是目标对象,第二个参数是想创建ref的对象上的属性名。如果想ref的属性是嵌套的,可以通过第一个参数设置。

toRefs

可以用于批量创建引用。

toRef一次只能处理一个属性,toRefs一次可以处理多个属性。

toRefs(对象)

toRefs可以用于对整个对象创建响应式副本。

<template><h2>{{ cat }}</h2><h2>{{ name }}</h2><h2>{{ hobby }}</h2>
</template><script>import { reactive,toRef,toRefs } from 'vue';export default{setup(){let data = reactive({name:'cat',age:10,hobby:{sleep:'day',walk:'night',}})let name = toRef(data,'name');let hobby = toRef(data.hobby,'sleep');let cat = toRefs(data); return {name,hobby,cat}}}
</script>

shallowReactive

浅Reactive。

只实现对象中的第一层数据的响应式,如果第二层数据发生变化,不触发响应式。

shallowRef

浅Ref。

不处理对象响应式,如果传入的是对象,无法实现响应式。

shallowReactive与shallowRef:

shallowReactive只处理对象最外层属性的响应式。shallowRef只处理基本数据类型的响应式,不对对象进行响应式。

使用场景:

如果对象的层级结构很深,但数据变化时只涉及最外层的变化,就可以使用shallowReactive创建响应式。

如果一个对象,后续不会修改对象中的数据,而是生成新对象来替换,可以使用shallowRef(shallowRef可以监测到对象整体的替换修改,但是无法监测到内部属性的变化)。

readonly

让一个响应式数据变为深度只读。

      let data = reactive({name:'cat',age:10,hobby:{sleep:'day',walk:'night',}})let cat = readonly(data)

shallowReadonly

让一个响应式数据变成浅只读。

第一层数据只可读,第二层及之后的数据可读可改。

readonly和shallowReadonly应用场景:当数据完全或者一定程度上不希望被修改时。

虽然在一开始定义数据时,数据创建的是响应式,初衷似乎是希望页面对数据的修改发生响应,而后又设置只读,不希望数据被修改,这种行为看起来有些令人迷惑,但在实际使用中,可能数据是其他人创建的,而目前我们不希望这个数据可写。就可以使用readonly和shallowReadonly对数据进行限制。

http://www.xdnf.cn/news/17908.html

相关文章:

  • RecyclerView 性能优化:从原理到实践的深度优化方案
  • 2020 GPT3 原文 Language Models are Few-Shot Learners 精选注解
  • JVM 总览与运行原理:深入Java虚拟机的核心引擎
  • 快速学会什么是gPRC
  • mysql-DDLy语句案例
  • Linux 系统中网络管理
  • vue3 wangeditor5 编辑器,使用方法
  • 高并发场景下限流算法对比与实践指南
  • 【递归、搜索与回溯算法】DFS解决FloodFill算法
  • whisper 语种检测学习笔记
  • 39 C++ STL模板库8-容器1-array
  • 解决hexo deploy报错:fatal: bad config line 1 in file .git/config
  • 跨网络 SSH 访问:借助 cpolar 内网穿透服务实现手机远程管理 Linux
  • 图像识别控制技术(Sikuli)深度解析:原理、应用与商业化前景
  • Vue 组件二次封装透传slots、refs、attrs、listeners
  • 把 AI 装进“冰箱贴”——基于超低功耗语音合成的小屏电子价签
  • StringBoot-SSE和WebFlux方式消息实时推送-默认单向-可增加交互接口
  • C语言中的输入输出函数:构建程序交互的基石
  • 开源数据发现平台:Amundsen Frontend Service 应用程序配置
  • 基于CodeBuddy的2D游戏开发实践:炫酷大便超人核心机制解析
  • NOI Online培训1至26期例题解析(16-20期)
  • week1-[一维数组]传送
  • MySQLl中OFFSET 的使用方法
  • PIDGenRc函数中lpstrRpc的由来和InitializePidVariables函数的关系
  • JMeter性能测试详细版(适合0基础小白学习--非常详细)
  • 基于SpringBoot的救援物资管理系统 受灾应急物资管理系统 物资管理小程序
  • 浏览器环境下AES-GCM JavaScript 加解密程序
  • Elasticsearch ABAC 配置:实现动态、细粒度的访问控制
  • 【C#】跨平台创建你的WinForms窗体应用(WindowsUbuntu)
  • 新手入门 Makefile:FPGA 项目实战教程(一)