vue3+Typescript---Composition API(常用部分)学习笔记(二)
1、計(jì)算屬性和監(jiān)視
(1)計(jì)算屬性
【computed函數(shù)】計(jì)算屬性默認(rèn)只有 getter,不過在需要時(shí)你也可以提供一個(gè) setter。
計(jì)算屬性的 getter 函數(shù)沒有副作用,它更易于測(cè)試和理解。
//第一個(gè)姓名 只有g(shù)etter的計(jì)算屬性const fullName1 = computed(() => {return user.firstName + "_" + user.lastName;});// 第二個(gè)姓名 有g(shù)etter與setter的計(jì)算屬性getter和setterconst fullName2 = computed({get() {console.log("get方法===");return user.firstName + "_" + user.lastName;},set(val: string) {console.log("set方法===", val);const name = val.split("_");user.firstName = name[0];user.lastName = name[1];},});計(jì)算屬性和methods方法的區(qū)別:
計(jì)算屬性是基于它們的反應(yīng)依賴關(guān)系緩存的。計(jì)算屬性只在相關(guān)響應(yīng)式依賴發(fā)生改變時(shí)它們才會(huì)重新求值。相比之下,每當(dāng)觸發(fā)重新渲染時(shí),調(diào)用方法將總會(huì)再次執(zhí)行函數(shù)。
(2)監(jiān)視
【watch函數(shù)】監(jiān)視指定的一個(gè)或多個(gè)響應(yīng)式數(shù)據(jù), 一旦數(shù)據(jù)變化, 就自動(dòng)執(zhí)行監(jiān)視回調(diào),默認(rèn)初始時(shí)不執(zhí)行回調(diào), 但可以通過配置immediate為true, 來指定初始時(shí)立即執(zhí)行第一次。通過配置deep為true, 來指定深度監(jiān)視。
// 第三個(gè)姓名const fullName3 = ref("");// 監(jiān)視指定的數(shù)據(jù)watch(user,({ firstName, lastName }) => {fullName3.value = firstName + "_" + lastName;},{ immediate: true, deep: true } //immediate默認(rèn)執(zhí)行一次watch,deep深度監(jiān)視);【watchEffect函數(shù)】不用直接指定要監(jiān)視的數(shù)據(jù), 回調(diào)函數(shù)中使用的哪些響應(yīng)式數(shù)據(jù)就監(jiān)視哪些響應(yīng)式數(shù)據(jù)。默認(rèn)初始時(shí)就會(huì)執(zhí)行第一次, 從而可以收集需要監(jiān)視的數(shù)據(jù)。監(jiān)視數(shù)據(jù)發(fā)生變化時(shí)回調(diào)。
//?監(jiān)視,不需要配置immediate,本身默認(rèn)就會(huì)進(jìn)行監(jiān)視(默認(rèn)執(zhí)行一次) watchEffect(()?=>?{fullName3.value?=?user.firstName?+?"_"?+?user.lastName; });例子
<template><h2>計(jì)算屬性和監(jiān)視</h2><fieldset><legend>姓名操作</legend>姓氏:<input v-model="user.firstName" type="text" placeholder="請(qǐng)輸入姓氏" /><br />名字:<inputv-model="user.lastName"type="text"placeholder="請(qǐng)輸入名字"/><br /></fieldset><fieldset><legend>計(jì)算屬性和監(jiān)視的演示</legend>姓名:<input v-model="fullName1" type="text" placeholder="顯示姓名" /><br />姓名:<input v-model="fullName2" type="text" placeholder="顯示姓名" /><br />姓名:<input v-model="fullName3" type="text" placeholder="顯示姓名" /><br /></fieldset> </template> <script lang="ts"> import {defineComponent,ref,reactive,computed,watch,watchEffect, } from "vue"; export default defineComponent({name: "App",setup() {const user = reactive({firstName: "雷",lastName: "朗朗",});//第一個(gè)姓名 只有g(shù)etter的計(jì)算屬性const fullName1 = computed(() => {return user.firstName + "_" + user.lastName;});// 第二個(gè)姓名 有g(shù)etter與setter的計(jì)算屬性getter和setterconst fullName2 = computed({get() {console.log("get方法===");return user.firstName + "_" + user.lastName;},set(val: string) {console.log("set方法===", val);const name = val.split("_");user.firstName = name[0];user.lastName = name[1];},});// 第三個(gè)姓名const fullName3 = ref("");// 監(jiān)視指定的數(shù)據(jù)watch(user,({ firstName, lastName }) => {fullName3.value = firstName + "_" + lastName;},{ immediate: true, deep: true } //immediate默認(rèn)執(zhí)行一次watch,deep深度監(jiān)視);// 監(jiān)視,不需要配置immediate,本身默認(rèn)就會(huì)進(jìn)行監(jiān)視(默認(rèn)執(zhí)行一次)// watchEffect(() => {// fullName3.value = user.firstName + "_" + user.lastName;// });// 監(jiān)視fullName3數(shù)據(jù),改變firstName和lastNamewatchEffect(() => {const name = fullName3.value.split("_");user.firstName = name[0];user.lastName = name[1];});// watch---可以監(jiān)視多個(gè)數(shù)據(jù),監(jiān)視非響應(yīng)式的數(shù)據(jù),采用回調(diào)函數(shù)的形式才可以watch([() => user.firstName, user.lastName, fullName3], () => {console.log("===執(zhí)行數(shù)據(jù)監(jiān)視===");});return {user,fullName1,fullName2,fullName3,};}, }); </script>2、生命周期
vue2對(duì)應(yīng)的鉤子函數(shù),vue3的鉤子函數(shù)先執(zhí)行,比如說?onMounted在mounted?前執(zhí)行。
| 說明 | vue2鉤子函數(shù) | vue3中對(duì)應(yīng)的組合式API |
| 組件實(shí)例化之前執(zhí)行 | beforeCreate | 使用?setup() |
| 組件實(shí)例化完畢,但頁(yè)面還未顯示 | created | 使用?setup() |
| 組件掛載前,頁(yè)面仍未顯示,但虛擬Dom已經(jīng)配置 | beforeMount | onBeforeMount |
| 組件掛載后,此方法執(zhí)行后,頁(yè)面顯示 | mounted? | onMounted |
| 組件更新前,頁(yè)面仍未更新,但虛擬Dom已經(jīng)配置 | beforeUpdate | onBeforeUpdate |
| 組件更新,此方法執(zhí)行后,頁(yè)面顯示 | updated | onUpdated |
| 組件銷毀前 | beforeDestroy | onBeforeUnmount |
| 組件銷毀 | destroyed | onUnmounted |
| 錯(cuò)誤處理機(jī)制 | errorCaptured | onErrorCaptured |
組合式 API 還提供了onRenderTracked、onRenderTriggered調(diào)試鉤子函數(shù)。
【App.vue】
<template><h2>APP父組件</h2><button?@click="showChild">是否顯示child</button><hr?/><child?v-if="isShow"></child> </template> <script?lang="ts">import?{?defineComponent,?ref,?reactive?}?from?"vue";import?Child?from?"./components/Child.vue";export?default?defineComponent({name:?"App",components:?{Child,},setup()?{const?isShow?=?ref(false);const?showChild?=?()?=>?{console.log("=====",?isShow.value);isShow.value?=?!isShow.value;};return?{isShow,showChild,};}, }); </script>【Child.vue】
<template><h2>Child子組件</h2><div>msg:{{ msg }}</div><button @click="update">更新數(shù)據(jù)</button> </template> <script lang="ts"> import {defineComponent,ref,onBeforeMount,onMounted,onUnmounted,onUpdated,onBeforeUnmount,onBeforeUpdate, } from "vue"; export default defineComponent({name: "Child",// vue2.x中的生命周期鉤子ebeforeCreate() {console.log("vue2.x中的beforeCreate");},created() {console.log("vue2.x中的created");},beforeMount() {console.log("vue2.x中的beforeMount");},mounted() {console.log("vue2.x中的mounted");},beforeUpdate() {console.log("vue2.x中的beforeUpdate");},updated() {console.log("vue2.x中的updated");},// vue2.x的beforeDestroy和destroyed這兩個(gè)生命周期回調(diào)已經(jīng)在vue3中改名了,所以不不能再用了// beforeDestroy() {// console.log("vue2.x中的beforeDestroy");// },// destroyed() {// console.log("vue2.x中的destroyed");// },beforeUnmount() {console.log("vue2.x中的beforeUnmount");},unmounted() {console.log("vue2.x中的unmounted");},setup() {console.log("vue3.0中的setup");const msg = ref("你好");const update = () => {msg.value += "==";};onBeforeMount(() => {console.log("vue3.0中的onBeforeMount");});onMounted(() => {console.log("vue3.0中的onMounted");});onBeforeUpdate(() => {console.log("vue3.0中的onBeforeUpdate");});onUpdated(() => {console.log("vue3.0中的onUpdated");});onBeforeUnmount(() => {console.log("vue3.0中的onBeforeUnmount");});onUnmounted(() => {console.log("vue3.0中的onUnmounted");});return {msg,update,};}, }); </script>3、自定義hook函數(shù)
使用Vue3的組合API封裝的可復(fù)用的功能函數(shù)
自定義hook的作用類似于vue2中的mixin技術(shù)
自定義Hook的優(yōu)勢(shì): 很清楚復(fù)用功能代碼的來源, 更清楚易
例子:自定義獲取當(dāng)前鼠標(biāo)點(diǎn)擊的坐標(biāo)的自定義hook函數(shù)。
【useMousePosition.ts】位于src->hook文件夾下
例子:封裝發(fā)ajax請(qǐng)求的hook函數(shù)
【products.json】位于public->data文件夾下。
【products.json】
[{"id":1,"title":"蘋果","price":4},{"id":2, "title":"哈密瓜","price":8},{"id":3,"title":"榴蓮","price":12} ]4、toRefs
把一個(gè)響應(yīng)式對(duì)象轉(zhuǎn)換成普通對(duì)象,該普通對(duì)象的每個(gè) property 都是一個(gè) ref。
將響應(yīng)式對(duì)象中所有屬性包裝為ref對(duì)象, 并返回包含這些ref對(duì)象的普通對(duì)象
應(yīng)用: 當(dāng)從合成函數(shù)返回響應(yīng)式對(duì)象時(shí),toRefs 非常有用,這樣消費(fèi)組件就可以在不丟失響應(yīng)式的情況下對(duì)返回的對(duì)象進(jìn)行分解使用。
<template><div>name:{{ name }}</div><div>age:{{ age }}</div><div>name:{{ name2 }}</div><div>age:{{ age2 }}</div> </template> <script lang="ts"> import { defineComponent, ref, reactive, toRefs } from "vue"; function useFeatureX() {const state = reactive({name2: "雷朗朗",age2: 2,});return {...toRefs(state),}; } export default defineComponent({name: "App",setup() {const a = ref("哈哈");console.log("a==", a);const state = reactive({name: "雷朗朗",age: 2,});console.log("state==", state);const state2 = toRefs(state); // toRefs可以把一個(gè)響應(yīng)式對(duì)象轉(zhuǎn)換成普通對(duì)象,該普通對(duì)象的每個(gè)property都是一個(gè)refconsole.log("state2==", state2);const { name2, age2 } = useFeatureX();// setInterval(() => {// name.value += "==";// console.log("==定時(shí)器執(zhí)行==");// }, 1000);return {...state2,name2,age2,};}, }); </script>?
總結(jié)
以上是生活随笔為你收集整理的vue3+Typescript---Composition API(常用部分)学习笔记(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 重构-五星评分
- 下一篇: 软件工程基础课-个人项目-数独