前端系列-9 Vue3生命周期和computed和watch

背景

本文介绍Vue3的生命周期和钩子函数,鉴于篇幅允许以及防止前端文章过于分散,因此将watch和computed部分之前的学习笔记也整理到本文中。这三部分是三个知识点。watch可以与pinia的$subscribe状态监听进行比较学习。

1.组件生命周期

vue的每个组件的生命周期都可以分为四个阶段:创建、挂载、更新、销毁;每个阶段的前后都提供了钩子函数,让开发者有机会在特定阶段运行自己的代码。这些钩子函数叫做生命周期钩子。

1\] setup : 最早执行的钩子函数, 在创建组件之前执行; \[2\] onBeforeMount和onMounted:组件挂载前后之前的函数; \[3\] onBeforeUpdate和onUpdated:组件更新前后执行的函数; \[4\] onBeforeUnmount和onUnmounted:组件卸载前后执行的函数; 具体使用方式如下所示: ```html ``` 组件加载后,Console控制台显示如下: ```shell setup before mount after mount ``` 当点击addNumBtn时,当前组件发生变化,触发更新事件,Console控制台显示如下: ```shell before update after update ``` **说明**:以onBeforeMount为例进行说明,在setup中执行onBeforeMount(函数参数),表示注册该组件在挂载前执行的方法,函数参数实际的执行时机为组件挂载前。VUE在生成和挂载组件时,按照深度优先的策略进行,子节点挂载完成后,才挂载父节点,即服务启动后,App.vue是最后一个挂载的组件。 ## 2.computed computed是vue3提供的响应式计算属性,可以根据其他响应式数据的变化而自动更新自身的值,并渲染到组件上。通过使用getter函数和setter函数来实现,访问计算属性时会调用getter计算并缓存计算结果;当依赖的响应式数据发生变化事,会再次调用getter计算并缓存新的计算结果;当修改计算属性时,调用setter函数进行更新。 > 说明: computed使用缓存是为了减少计算次数以提高性能;只有数据发生才会重新计算 以下通过案例进行介绍: ```javascript ``` 在页面上,点击**修改按钮** 时,num和computedNum在页面上发送变化。 如果新增一个按钮用于修改computedNum的值并触发修改,此时页面不会发生变化,浏览器控制台告警显示:`[Vue warn] Write operation failed: computed value is readonly.`即上述给computed传递一个函数的语法定义的计算属性为只读(不可写)。 如要求computed计算属性支持可读写,需要按如下方式修改: ```javascript // 只读 let computedNum = computed( ()=>{return num.value * 100;} ) // 可读可写 let computedSetNum = computed({ get(){ return num.value * 123; }, set(value) { num.value=value; } }); ``` **说明**:computed传递一个对象,对象包含了get()和set(value)方法,分别用于读数据和写数据时调用。 ## 3.watch 在"前端系列-8 集中式状态管理工具pinia"中介绍过可以通过store对象的$subscribe监听状态的变化,一般用于全局变量,而组件内部的变量可用watch实现监听。 watch一般用于监听ref和reactive包装的响应式对象,以及它们构成的数组。在不同场景下,watch使用方式有所区别,以下结合案例分章节分别进行介绍。 ### 3.1 ref基本变量 > 监听基本变量 ```javascript const num = ref(0) watch(num, (newValue, oldValue) => { console.log('num updated', newValue) }) ``` 在setup中直接调用watch方法进行注册监听,同时传递两个参数: \[1\]要监听的变量和\[2\]处理函数。其中, 处理函数有两个入参,分别表示更新后的值和更新前的值;当监听的变量发生变化时,处理函数会被调用。 ### 3.2 ref 对象变量 ref对象被watch时,需要多传入一个配置对象,用于指定深度递归;否则监听的是ref对象的地址,即ref属性发生变化时,watch监听不会被触发。正确的使用方式如下: ```javascript const person = ref({ name: 'ewen', age: '19', address: { country: 'CN', area: 'NanJing' } }) watch(person, (newValue, oldValue) => { console.log('person update', newValue) }, { deep: true } ) ``` `{ deep: true }`对象deep表示是否进行深度递归,即子孙属性变化时,是否触发watch监听。 初次之外,还可以配置 immediate项,true表示立即触发(创建watch监听时触发,旧值为空),false表示第一次更新时触发。 ### 3.3 reactive对象变量 #### 3.3.1 监听整个变量 ```javascript const person = reactive({ name: 'ewen', age: '19', address: { country: 'CN', area: 'NanJing' } }) watch(person, (newValue, oldValue) => { console.log('person update', newValue) }) ``` 当person的属性(含属性的子属性...)有变化时,都会触发watch监听。 #### 3.3.2 监听变量的某个属性 ```javascript // 监听整个person对象 watch(person, (newValue, oldValue) => {...} // 等价于 watch(() => person, (newValue, oldValue) => {...} // 监听person对象的某个属性 watch( () => person.name, (newValue, oldValue) => {...} ``` ### 3.4 组合监听 当多个ref对象、reactive对象变化时触发相同的逻辑(如打印日志),可以分别定义watch监听;也可对这些对象进行组合监听。将前面的变量修改为数组即可,如下所示: ```javascript // 使用时注意监听变量和参数的对应顺序 watch([() => num, person.name], ([newNum, newPerson], [oldNum, oldPerson]) => { console.log('data updated') }) ```

相关推荐
腾讯TNTWeb前端团队1 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰4 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪4 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪4 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy5 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom6 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom6 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom6 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom6 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom6 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试