Vue3 入坑 Chapter 3
聲明周期
Vue2生命周期
Vue3聲明周期
Vue2 與 Vue3 版本生命周期相對應(yīng)的組合式 API
beforeCreate -> 使用 setup()
created -> 使用 setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted
errorCaptured -> onErrorCaptured
示例代碼
父組件中
<template>
<div class="lifeCycleTest">
<h2>APP父級組件</h2>
<button @click="isShow=!isShow">切換顯示</button>
<hr />
<lifecycle-child-test v-if="isShow"></lifecycle-child-test>
<hr />
<lifecycle-child-test2 v-if="isShow"></lifecycle-child-test2>
</div>
</template>
<script lang="ts">
import LifecycleChildTest from '@/components/LifecycleChildTest.vue'
import LifecycleChildTest2 from '@/components/LifecycleChildTest2.vue'
import { defineComponent, ref } from 'vue'
export default defineComponent({
name: 'LifecycleTest',
// 注冊組件
components: {
LifecycleChildTest,
LifecycleChildTest2
},
setup () {
const isShow = ref(true)
return {
isShow
}
}
})
</script>
<style lang="scss" scoped>
</style>
子組件1中(Vue2)
<template>
<div class="LifecycleChildTest">
<h2>Child子級組件, Vue2的用法</h2>
<h4>msg: {{ msg }}</h4>
<button @click="update">更新數(shù)據(jù)</button>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
export default defineComponent({
name: 'LifecycleChildTest',
beforeCreate () {
console.log('Vue2中的beforeCreate...')
},
created () {
console.log('Vue2中的created...')
},
beforeMount () {
console.log('Vue2中的beforeMount...')
},
mounted () {
console.log('Vue2中的mounted...')
},
beforeUpdate () {
console.log('Vue2中的beforeUpdate...')
},
updated () {
console.log('Vue2中的updated...')
},
beforeUnmount () {
console.log('Vue2中的beforeDestroy...')
},
unmounted () {
console.log('Vue2中的created...')
},
setup () {
// 響應(yīng)式數(shù)據(jù)
const msg = ref('abc')
// 按鈕點(diǎn)擊事件的回調(diào)
const update = () => {
msg.value += '==='
}
return { msg, update }
}
})
</script>
<style lang="scss" scoped>
</style>
子組件2中(Vue3)
<template>
<div class="LifecycleChildTest">
<h2>Child子級組件2, Vue3的用法</h2>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue'
export default defineComponent({
name: 'LifecycleChildTest',
setup () {
console.log('Vue3中的 setup')
// 響應(yīng)式數(shù)據(jù)
const msg = ref('abc')
// 按鈕點(diǎn)擊事件的回調(diào)
const update = () => {
msg.value += '==='
}
onBeforeMount(() => {
console.log('Vue3中的onBeforeMount...')
})
onMounted(() => {
console.log('Vue3中的onMounted')
})
onBeforeUpdate(() => {
console.log('Vue3中的onBeforeUpdate')
})
onUpdated(() => {
console.log('Vue3中的onUpdated')
})
onBeforeUnmount(() => {
console.log('Vue3中的onBeforeUnmount')
})
onUnmounted(() => {
console.log('Vue3中的onUnmounted')
})
}
})
</script>
<style lang="scss" scoped>
</style>
自定義Hook函數(shù)
自定義Hook函數(shù): useMousePosition.ts
import { onBeforeUnmount, onMounted, ref } from 'vue'
// 此處應(yīng)該寫出函數(shù)的返回值類型
// eslint-disable-next-line
export default function () {
const x = ref(-1)
const y = ref(-1)
// 點(diǎn)擊事件的回調(diào)函數(shù)
const clickHandler = (event: MouseEvent) => {
x.value = event.pageX
y.value = event.pageY
}
// 頁面已經(jīng)加載完畢了, 再進(jìn)行點(diǎn)擊的操作
// 頁面加載完畢的生命周期
onMounted(() => {
window.addEventListener('click', clickHandler)
})
// 頁面卸載之前的聲明周期組合API
onBeforeUnmount(() => {
window.removeEventListener('click', clickHandler)
})
return { x, y }
}
自定義Hook函數(shù): useRequest.ts (用于發(fā)送AJAX請求)
import { ref } from 'vue'
// 引入 axios
import axios from 'axios'
// 發(fā)送 ajax 請求, 此處應(yīng)該寫出函數(shù)的返回值類型
// eslint-disable-next-line
export default function <T> (url: string) {
// 加載的狀態(tài)
const loading = ref(true)
// 請求成功的數(shù)據(jù)
const data = ref<T | null>(null) // 坑
// 錯誤信息
const errorMsg = ref('')
// 發(fā)送請求
axios.get(url).then(rs => {
// 改變加載狀態(tài)
loading.value = false
data.value = rs.data
})
.catch(error => {
loading.value = false
errorMsg.value = error.message || '未知錯誤'
})
return {
loading,
data,
errorMsg
}
}
業(yè)務(wù)組件中 CustomHookTest.vue
<template>
<div class="customHookTest">
<h2>自定義hook函數(shù)操作</h2>
<h2>x: {{ x }}, y: {{ y }}</h2>
<h3 v-if="loading">正在加載中...</h3>
<h3 v-else-if="errorMsg">錯誤信息: {{ errorMsg }}</h3>
<ul v-else>
<li>id: {{ data.id }}</li>
<li>address: {{ data.address }}</li>
<li>distance: {{ data.distance }}</li>
</ul>
<hr>
<!-- 數(shù)組數(shù)據(jù) -->
<ul v-for="item in data" :key="item.id">
<li>id: {{ item.id }}</li>
<li>title: {{ item.title }}</li>
<li>price: {{ item.price }}</li>
</ul>
</div>
</template>
<script lang="ts">
import { defineComponent, watch } from 'vue'
import useMousePosition from '@/hooks/useMousePosition'
import useRequest from '@/hooks/useRequest'
// 定義接口, 約束對象的類型
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface IAddressData {
id: number,
address: string,
distance: string,
}
interface IProductData {
id: string,
title: string,
price: number,
}
export default defineComponent({
name: 'customHookTest',
// 需求1: 用戶給在頁面中點(diǎn)擊頁面, 把點(diǎn)擊的位置的橫縱坐標(biāo)收集并展示出來
setup () {
const { x, y } = useMousePosition()
// const { loading, data, errorMsg } = useRequest<IAddressData>('/mock/address.json') // 獲取對象數(shù)據(jù)
const { loading, data, errorMsg } = useRequest<IProductData[]>('/mock/products.json') // 獲取數(shù)組數(shù)據(jù)
// 監(jiān)視
watch(data, () => {
if (data.value) {
console.log(data.value.length)
}
})
return {
x, y, loading, data, errorMsg
}
}
})
</script>
<style lang="scss" scoped>
</style>