uni-app Lifecycle Guide
This guide provides a detailed introduction to uni-app lifecycles, including application lifecycle, page lifecycle, and component lifecycle, to help you better understand and use uni-app.
Overview
Lifecycle refers to functions triggered at specific time points during the entire process from application creation to destruction, where developers can execute their own code logic.
uni-app Lifecycle Categories
Type | Description | Listening Location |
---|---|---|
Application Lifecycle | Application-level lifecycle functions | Listen in App.vue |
Page Lifecycle | Page-level lifecycle functions | Listen in pages |
Component Lifecycle | Component-level lifecycle functions | Listen in components |
Application Lifecycle
Application lifecycle refers to functions triggered at specific time points during the process from uni-app startup to unloading. These functions are defined in App.vue
.
Lifecycle Functions
Function | Description | Parameters | Use Cases |
---|---|---|---|
onLaunch | Triggered when application initialization is complete (triggered only once globally) | options (startup parameters) | Initialize app data, check updates, get user info |
onShow | Triggered when application starts or enters foreground from background | options (startup parameters) | Restore app state, refresh data, track usage time |
onHide | Triggered when application enters background from foreground | - | Pause audio/video playback, save app state, pause timers |
onError | Triggered when application encounters runtime errors | err (error information) | Error log collection, exception reporting |
onUniNViewMessage | Listen to data sent from nvue pages | event (message object) | Receive messages from nvue pages |
Application Lifecycle Example
<script>
export default {
onLaunch: function(options) {
console.log('App Launch')
console.log('Launch parameters:', options)
// Initialize application data
this.checkUpdate()
this.getUserInfo()
},
onShow: function(options) {
console.log('App Show')
console.log('Show parameters:', options)
// Restore application state
this.resumeAudio()
this.startTimer()
},
onHide: function() {
console.log('App Hide')
// Save application state
this.pauseAudio()
this.stopTimer()
},
onError: function(err) {
console.log('App Error')
console.error(err)
// Error reporting
this.reportError(err)
},
methods: {
checkUpdate() {
// Update checking logic
uni.getUpdateManager && uni.getUpdateManager().onCheckForUpdate((res) => {
if (res.hasUpdate) {
console.log('New version found')
}
})
},
getUserInfo() {
// Get user info logic
uni.getUserInfo({
success: (res) => {
console.log('User info:', res.userInfo)
}
})
},
resumeAudio() {
// Resume audio playback logic
const audioContext = uni.createInnerAudioContext()
audioContext.play()
},
pauseAudio() {
// Pause audio playback logic
const audioContext = uni.createInnerAudioContext()
audioContext.pause()
},
startTimer() {
// Start timer logic
this.timer = setInterval(() => {
console.log('Timer task executed')
}, 60000)
},
stopTimer() {
// Stop timer logic
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
},
reportError(err) {
// Error reporting logic
uni.request({
url: 'https://api.example.com/error-report',
method: 'POST',
data: {
error: err.toString(),
timestamp: Date.now()
}
})
}
}
}
</script>
Page Lifecycle
Page lifecycle refers to functions triggered at specific time points during the process from uni-app page loading to unloading. These functions are defined in the page's vue file.
Page Lifecycle Execution Order
Page Load → onLoad → onShow → onReady
Page Switch → onHide → Other Page → onShow
Page Unload → onUnload
Lifecycle Functions
Function | Description | Parameters | Trigger Timing |
---|---|---|---|
onLoad | Triggered when page loads | options (page parameters) | When page loads, triggered only once |
onShow | Triggered when page shows | - | When page shows/enters foreground |
onReady | Triggered when page initial rendering is complete | - | When page initial rendering is complete, triggered only once |
onHide | Triggered when page hides | - | When page hides/enters background |
onUnload | Triggered when page unloads | - | When page unloads |
onPullDownRefresh | Triggered on pull-to-refresh | - | When user pulls down to refresh |
onReachBottom | Triggered when reaching bottom | - | When page scrolls to bottom |
onPageScroll | Triggered on page scroll | Object | When page scrolls |
onTabItemTap | Triggered on tab click | Object | When clicking tab (tabBar pages only) |
Page Lifecycle Details
onLoad - Page Load
Trigger Timing: Triggered when page loads, only once
Parameters: options (data passed from previous page)
Use Cases:
- Get page parameters
- Initialize page data
- Make network requests for initial data
onLoad: function(options) {
console.log('Page load complete')
console.log('Page parameters:', options)
// Initialize page data
this.productId = options.id
this.loadProductDetail(options.id)
}
onShow - Page Show
Trigger Timing: Triggered when page shows/enters foreground
Use Cases:
- Refresh page data
- Restore page state
- Start audio/video playback
onShow: function() {
console.log('Page show')
// Refresh cart data
this.refreshCartData()
// Restore page state
this.resumeVideoPlay()
}
onReady - Page Rendering Complete
Trigger Timing: Triggered when page initial rendering is complete, only once
Use Cases:
- Get page elements
- Initialize complex components like charts
- Execute operations that need to be performed after page rendering
onReady: function() {
console.log('Page initial rendering complete')
// Get page elements
const query = uni.createSelectorQuery()
query.select('#chart').boundingClientRect(data => {
// Initialize chart
this.initChart(data.width, data.height)
}).exec()
}
onHide - Page Hide
Trigger Timing: Triggered when page hides/enters background
Use Cases:
- Pause audio/video playback
- Save page state
- Pause timers and other power-consuming operations
onHide: function() {
console.log('Page hide')
// Pause video playback
this.pauseVideo()
// Save edit state
this.saveEditState()
// Pause timer
clearInterval(this.timer)
}
onUnload - Page Unload
Trigger Timing: Triggered when page unloads
Use Cases:
- Clean up page resources
- Cancel network requests
- Close long connections
onUnload: function() {
console.log('Page unload')
// Clean up resources
this.disposeChart()
// Cancel network requests
this.cancelRequest()
// Close socket connection
this.closeSocket()
}
onPullDownRefresh - Pull to Refresh
Trigger Timing: Triggered when user pulls down to refresh
Use Cases:
- Refresh page data
- Reload resources
Note: Need to configure enablePullDownRefresh
as true in pages.json
onPullDownRefresh: function() {
console.log('User pull down refresh')
// Reload data
this.loadData().then(() => {
// Stop pull-to-refresh after data loading is complete
uni.stopPullDownRefresh()
})
}
onReachBottom - Reach Bottom
Trigger Timing: Triggered when page scrolls to bottom
Use Cases:
- Load more data
- Implement pagination loading
Note: Can configure onReachBottomDistance
in pages.json to set trigger distance
onReachBottom: function() {
console.log('Page scrolled to bottom')
if (!this.isLoading && !this.isEnd) {
this.isLoading = true
this.page++
this.loadMoreData().then(() => {
this.isLoading = false
})
}
}
onPageScroll - Page Scroll
Trigger Timing: Triggered when page scrolls
Parameters: Object containing scrollTop property, indicating the distance the page has scrolled vertically (in px)
Use Cases:
- Implement sticky effects
- Show/hide back-to-top button
- Adjust UI based on scroll position
Note: Triggered frequently, consider throttling
onPageScroll: function(e) {
// Use throttle function to handle scroll events
if (this.scrollTimer) return
this.scrollTimer = setTimeout(() => {
this.scrollTimer = null
// Show/hide back-to-top button based on scroll position
this.showBackToTop = e.scrollTop > 100
// Implement sticky effect
this.isFixed = e.scrollTop > 200
}, 100)
}
onTabItemTap - Tab Click
Trigger Timing: Triggered when clicking tab, only exists in tabBar pages
Parameters: Object containing pagePath, text, index properties
Use Cases:
- Track tab click events
- Refresh page when clicking current tab
- Custom tab click behavior
onTabItemTap: function(e) {
console.log('Tab clicked', e)
// If clicking current tab, refresh page
if (e.index === this.currentTabIndex) {
this.refreshPage()
}
// Track click event
this.reportTabClick(e.index)
}
Complete Page Lifecycle Example
<template>
<view class="page">
<view class="content">
<text class="title">Page Lifecycle Example</text>
<view class="data-area">
<text>Data: {{ dataList.length }} items</text>
</view>
<view class="button-area">
<button type="primary" @click="refreshData">Refresh Data</button>
</view>
</view>
<view class="list-area">
<view v-for="(item, index) in dataList" :key="index" class="list-item">
{{ item.name }}
</view>
</view>
<view class="loading" v-if="isLoading">Loading...</view>
<view class="back-to-top" v-if="showBackToTop" @click="backToTop">
<text class="back-icon">↑</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
dataList: [],
page: 1,
isLoading: false,
isEnd: false,
showBackToTop: false,
scrollTimer: null,
productId: ''
}
},
// Page load
onLoad(options) {
console.log('Page load', options)
this.productId = options.id || ''
this.loadData()
},
// Page show
onShow() {
console.log('Page show')
this.refreshCartData()
},
// Page rendering complete
onReady() {
console.log('Page initial rendering complete')
const query = uni.createSelectorQuery()
query.select('.content').boundingClientRect(data => {
console.log('Content area height:', data.height)
}).exec()
},
// Page hide
onHide() {
console.log('Page hide')
this.savePageState()
},
// Page unload
onUnload() {
console.log('Page unload')
if (this.scrollTimer) {
clearTimeout(this.scrollTimer)
}
},
// Pull to refresh
onPullDownRefresh() {
console.log('Pull to refresh')
this.page = 1
this.isEnd = false
this.loadData().then(() => {
uni.stopPullDownRefresh()
})
},
// Reach bottom
onReachBottom() {
console.log('Load more')
if (!this.isLoading && !this.isEnd) {
this.loadMoreData()
}
},
// Page scroll
onPageScroll(e) {
if (this.scrollTimer) return
this.scrollTimer = setTimeout(() => {
this.scrollTimer = null
this.showBackToTop = e.scrollTop > 100
}, 100)
},
methods: {
// Load initial data
loadData() {
this.isLoading = true
return new Promise((resolve) => {
setTimeout(() => {
this.dataList = Array.from({length: 20}, (_, i) => ({
id: i + 1,
name: `Product ${i + 1}`
}))
this.isLoading = false
resolve()
}, 1000)
})
},
// Load more data
loadMoreData() {
if (this.page >= 5) {
this.isEnd = true
return Promise.resolve()
}
this.isLoading = true
return new Promise((resolve) => {
setTimeout(() => {
const moreData = Array.from({length: 20}, (_, i) => ({
id: this.dataList.length + i + 1,
name: `Product ${this.dataList.length + i + 1}`
}))
this.dataList = [...this.dataList, ...moreData]
this.page++
this.isLoading = false
resolve()
}, 1000)
})
},
// Refresh data
refreshData() {
this.page = 1
this.isEnd = false
this.loadData()
},
// Refresh cart data
refreshCartData() {
console.log('Refresh cart data')
},
// Save page state
savePageState() {
console.log('Save page state')
uni.setStorageSync('pageState', {
scrollTop: this.scrollTop,
page: this.page
})
},
// Back to top
backToTop() {
uni.pageScrollTo({
scrollTop: 0,
duration: 300
})
}
}
}
</script>
<style scoped>
.page {
padding: 20px;
}
.content {
margin-bottom: 20px;
}
.title {
font-size: 18px;
font-weight: bold;
margin-bottom: 10px;
}
.data-area {
margin: 10px 0;
color: #666;
}
.button-area {
margin: 15px 0;
}
.list-area {
margin-top: 20px;
}
.list-item {
padding: 15px;
border-bottom: 1px solid #eee;
background-color: #fff;
}
.loading {
text-align: center;
padding: 15px;
color: #999;
}
.back-to-top {
position: fixed;
right: 20px;
bottom: 30px;
width: 40px;
height: 40px;
background-color: rgba(0, 0, 0, 0.5);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
z-index: 999;
}
.back-icon {
font-size: 20px;
}
</style>
Component Lifecycle
uni-app component lifecycle follows Vue component lifecycle and also supports uni-app page lifecycle.
Vue 2 Component Lifecycle
Lifecycle | Description | Use Cases |
---|---|---|
beforeCreate | Before component instance is created | Component options object is created, but instance is not yet created |
created | Component instance is created | Initialize data, call APIs, etc. |
beforeMount | Before component mounting | Template is compiled but not yet mounted to DOM |
mounted | Component mounting complete | Get DOM elements, initialize third-party libraries, etc. |
beforeUpdate | Before component update | Data is updated but DOM is not yet re-rendered |
updated | Component update complete | DOM operations after update |
beforeDestroy | Before component destruction | Clean up timers, cancel event listeners, etc. |
destroyed | Component destruction complete | Component instance is destroyed |
Vue 3 Component Lifecycle
Lifecycle | Description | Vue 2 Equivalent | Use Cases |
---|---|---|---|
setup | Component initialization | beforeCreate/created | Entry point for Composition API |
onBeforeMount | Before component mounting | beforeMount | Preparation work before mounting |
onMounted | Component mounting complete | mounted | Get DOM elements, initialize third-party libraries, etc. |
onBeforeUpdate | Before component update | beforeUpdate | Preparation work before update |
onUpdated | Component update complete | updated | DOM operations after update |
onBeforeUnmount | Before component unmounting | beforeDestroy | Clean up timers, cancel event listeners, etc. |
onUnmounted | Component unmounting complete | destroyed | Component instance is destroyed |
Component Lifecycle Examples
Vue 2 Component Example
<template>
<view class="component">
<text>{{ message }}</text>
<button @click="updateMessage">Update Message</button>
</view>
</template>
<script>
export default {
data() {
return {
message: 'Initial message',
timer: null
}
},
beforeCreate() {
console.log('beforeCreate: Before component instance is created')
},
created() {
console.log('created: Component instance is created')
// Initialize data
this.initData()
},
beforeMount() {
console.log('beforeMount: Before component mounting')
},
mounted() {
console.log('mounted: Component mounting complete')
// Start timer
this.timer = setInterval(() => {
console.log('Timer running...')
}, 2000)
},
beforeUpdate() {
console.log('beforeUpdate: Before component update')
},
updated() {
console.log('updated: Component update complete')
},
beforeDestroy() {
console.log('beforeDestroy: Before component destruction')
// Clean up timer
if (this.timer) {
clearInterval(this.timer)
}
},
destroyed() {
console.log('destroyed: Component destruction complete')
},
methods: {
initData() {
console.log('Initialize data')
},
updateMessage() {
this.message = 'Updated message: ' + Date.now()
}
}
}
</script>
Vue 3 Component Example
<template>
<view class="component">
<text>{{ message }}</text>
<button @click="updateMessage">Update Message</button>
</view>
</template>
<script setup>
import {
ref,
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted
} from 'vue'
// Reactive data
const message = ref('Initial message')
let timer = null
// Lifecycle hooks
console.log('setup: Component initialization')
onBeforeMount(() => {
console.log('onBeforeMount: Before component mounting')
})
onMounted(() => {
console.log('onMounted: Component mounting complete')
// Start timer
timer = setInterval(() => {
console.log('Timer running...')
}, 2000)
})
onBeforeUpdate(() => {
console.log('onBeforeUpdate: Before component update')
})
onUpdated(() => {
console.log('onUpdated: Component update complete')
})
onBeforeUnmount(() => {
console.log('onBeforeUnmount: Before component unmounting')
// Clean up timer
if (timer) {
clearInterval(timer)
}
})
onUnmounted(() => {
console.log('onUnmounted: Component unmounting complete')
})
// Methods
function updateMessage() {
message.value = 'Updated message: ' + Date.now()
}
// Initialize data
function initData() {
console.log('Initialize data')
}
// Execute initialization
initData()
</script>
Lifecycle Best Practices
Usage Recommendations
Recommendation | Description |
---|---|
Use lifecycle appropriately | Choose appropriate lifecycle hooks based on different business needs, avoid executing complex operations in unnecessary hooks |
Avoid blocking rendering | Avoid executing time-consuming operations in lifecycle hooks like onLoad and onShow, which may block page rendering |
Resource management | Clean up resources like timers and event listeners in onUnload and beforeDestroy |
Data fetching | Page data fetching is recommended in onLoad rather than onShow to avoid duplicate requests |
State restoration | Restore page state in onShow, such as audio/video playback state |
Common Issues and Solutions
1. Data Not Refreshing When Returning to Page
Problem: Navigate from page A to page B, then return to page A, but page A data is not refreshed.
Cause: When returning to previous page, onShow is triggered instead of onLoad.
Solutions:
- Refresh data in onShow
- Use page stack management to refresh data when returning
- Use global event bus, trigger event after B page operation is complete, A page listens to event and refreshes data
// Page A
onShow() {
// Check if returning from page B
const pages = getCurrentPages()
if (pages.length > 1 && pages[pages.length - 1].route.includes('pageA')) {
this.refreshData()
}
}
// Or use global events
onLoad() {
uni.$on('updateData', () => {
this.refreshData()
})
}
onUnload() {
uni.$off('updateData')
}
// After page B operation is complete
uni.$emit('updateData')
2. Page Lifecycle Execution Order Issues
Problem: Unclear about the execution order of various lifecycles during page navigation.
Solution: Understand the lifecycle execution order during page navigation:
- A page navigates to B page:
A.onHide
→B.onLoad
→B.onShow
→B.onReady
- B page returns to A page:
B.onUnload
→A.onShow
3. Relationship Between Component and Page Lifecycles
Problem: Unclear about the execution order and relationship between component and page lifecycles.
Solution: Understand the relationship between component and page lifecycles:
- Page loading:
Page onLoad
→Component beforeCreate
→Component created
→Component beforeMount
→Component mounted
→Page onShow
→Page onReady
- Page unloading:
Page onUnload
→Component beforeDestroy
→Component destroyed
4. Memory Leak Issues
Problem: After page navigation, resources like timers and event listeners from the original page are not released, causing memory leaks.
Solution: Clean up resources when page unloads:
onLoad() {
// Create timer
this.timer = setInterval(() => {
this.doSomething()
}, 1000)
// Add event listener
uni.$on('customEvent', this.handleEvent)
}
onUnload() {
// Clean up timer
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
// Remove event listener
uni.$off('customEvent', this.handleEvent)
}
Summary
uni-app lifecycle is an important concept in development. Correctly understanding and using lifecycle can:
- Improve application performance
- Avoid memory leaks
- Optimize user experience
- Simplify state management
It's recommended to choose appropriate lifecycle hooks based on specific business needs in actual development and pay attention to timely resource cleanup.
Related Links
- Project Structure - Learn about uni-app project file structure
- Basic Components - Learn how to use uni-app basic components
- API Usage - Master the API interfaces provided by uni-app