You've already forked Pandona-Engine
初始化提交
This commit is contained in:
564
guide/essentials/lifecycle.md
Normal file
564
guide/essentials/lifecycle.md
Normal file
@@ -0,0 +1,564 @@
|
||||
# 生命周期
|
||||
|
||||
PE引擎为场景提供了完整的生命周期钩子,让你能够在适当的时机执行初始化、清理和其他操作。理解生命周期对于开发高效、稳定的PE应用至关重要。
|
||||
|
||||
## 生命周期钩子概览
|
||||
|
||||
每个PE场景都有四个主要的生命周期钩子:
|
||||
|
||||
1. **onLoad** - 场景加载时调用(只执行一次)
|
||||
2. **onShow** - 场景显示时调用(每次显示都会执行)
|
||||
3. **onHide** - 场景隐藏时调用
|
||||
4. **onDestory** - 场景销毁时调用(只执行一次)
|
||||
|
||||
## onLoad
|
||||
|
||||
`onLoad`钩子在场景首次加载时调用,只执行一次。这是进行一次性初始化操作的最佳时机。
|
||||
|
||||
```html
|
||||
<sence>
|
||||
<box class="welcome">欢迎来到PE引擎</box>
|
||||
</sence>
|
||||
|
||||
<script>
|
||||
// 在onLoad中进行一次性初始化
|
||||
onLoad(() => {
|
||||
console.log('场景加载完成')
|
||||
|
||||
// 初始化数据
|
||||
initializeData()
|
||||
|
||||
// 设置初始状态
|
||||
setupInitialState()
|
||||
|
||||
// 加载资源
|
||||
loadResources()
|
||||
|
||||
// 添加全局事件监听器
|
||||
document.addEventListener('keydown', handleGlobalKeyDown)
|
||||
})
|
||||
|
||||
function initializeData() {
|
||||
// 初始化应用数据
|
||||
console.log('初始化数据')
|
||||
}
|
||||
|
||||
function setupInitialState() {
|
||||
// 设置初始状态
|
||||
console.log('设置初始状态')
|
||||
}
|
||||
|
||||
function loadResources() {
|
||||
// 加载必要的资源
|
||||
console.log('加载资源')
|
||||
}
|
||||
|
||||
function handleGlobalKeyDown(event) {
|
||||
// 处理全局键盘事件
|
||||
if (event.key === 'Escape') {
|
||||
PE.navigateTo('/')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
## onShow
|
||||
|
||||
`onShow`钩子在场景每次显示时调用。无论是首次显示还是从其他场景切换回来,都会执行此钩子。
|
||||
|
||||
```html
|
||||
<sence>
|
||||
<box class="content">场景内容</box>
|
||||
<text class="last-updated">最后更新: {{ lastUpdated }}</text>
|
||||
</sence>
|
||||
|
||||
<script>
|
||||
let lastUpdated = ''
|
||||
|
||||
onShow(() => {
|
||||
console.log('场景显示')
|
||||
|
||||
// 更新时间戳
|
||||
updateTimestamp()
|
||||
|
||||
// 刷新数据
|
||||
refreshData()
|
||||
|
||||
// 启动动画
|
||||
startAnimations()
|
||||
|
||||
// 恢复定时器
|
||||
resumeTimers()
|
||||
})
|
||||
|
||||
function updateTimestamp() {
|
||||
lastUpdated = new Date().toLocaleString()
|
||||
const timeElement = game.getSceneElement('last-updated')
|
||||
if (timeElement) {
|
||||
timeElement.element.textContent = `最后更新: ${lastUpdated}`
|
||||
}
|
||||
}
|
||||
|
||||
function refreshData() {
|
||||
// 刷新场景数据
|
||||
console.log('刷新数据')
|
||||
}
|
||||
|
||||
function startAnimations() {
|
||||
// 启动场景动画
|
||||
console.log('启动动画')
|
||||
}
|
||||
|
||||
function resumeTimers() {
|
||||
// 恢复定时器
|
||||
console.log('恢复定时器')
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
## onHide
|
||||
|
||||
`onHide`钩子在场景隐藏时调用,比如切换到其他场景时。
|
||||
|
||||
```html
|
||||
<sence>
|
||||
<box class="content">场景内容</box>
|
||||
</sence>
|
||||
|
||||
<script>
|
||||
onHide(() => {
|
||||
console.log('场景隐藏')
|
||||
|
||||
// 暂停动画
|
||||
pauseAnimations()
|
||||
|
||||
// 暂停定时器
|
||||
pauseTimers()
|
||||
|
||||
// 保存状态
|
||||
saveState()
|
||||
})
|
||||
|
||||
function pauseAnimations() {
|
||||
// 暂停场景动画
|
||||
console.log('暂停动画')
|
||||
}
|
||||
|
||||
function pauseTimers() {
|
||||
// 暂停定时器
|
||||
console.log('暂停定时器')
|
||||
}
|
||||
|
||||
function saveState() {
|
||||
// 保存场景状态
|
||||
console.log('保存状态')
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
## onDestory
|
||||
|
||||
`onDestory`钩子在场景销毁时调用,通常发生在应用关闭或场景被永久移除时。
|
||||
|
||||
```html
|
||||
<sence>
|
||||
<box class="content">场景内容</box>
|
||||
</sence>
|
||||
|
||||
<script>
|
||||
onDestory(() => {
|
||||
console.log('场景销毁')
|
||||
|
||||
// 清理资源
|
||||
cleanupResources()
|
||||
|
||||
// 移除事件监听器
|
||||
removeEventListeners()
|
||||
|
||||
// 停止所有动画
|
||||
stopAllAnimations()
|
||||
|
||||
// 清理定时器
|
||||
clearAllTimers()
|
||||
})
|
||||
|
||||
function cleanupResources() {
|
||||
// 清理加载的资源
|
||||
console.log('清理资源')
|
||||
}
|
||||
|
||||
function removeEventListeners() {
|
||||
// 移除添加的事件监听器
|
||||
document.removeEventListener('keydown', handleGlobalKeyDown)
|
||||
console.log('移除事件监听器')
|
||||
}
|
||||
|
||||
function stopAllAnimations() {
|
||||
// 停止所有动画
|
||||
console.log('停止所有动画')
|
||||
}
|
||||
|
||||
function clearAllTimers() {
|
||||
// 清理所有定时器
|
||||
console.log('清理定时器')
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
## 生命周期执行顺序
|
||||
|
||||
理解生命周期钩子的执行顺序对于正确管理场景状态非常重要:
|
||||
|
||||
### 首次加载场景
|
||||
|
||||
1. `onLoad` - 场景加载时执行(一次)
|
||||
2. `onShow` - 场景显示时执行
|
||||
|
||||
### 切换到其他场景
|
||||
|
||||
1. 当前场景: `onHide` - 场景隐藏时执行
|
||||
|
||||
### 切换回场景
|
||||
|
||||
1. `onShow` - 场景显示时执行
|
||||
|
||||
### 销毁场景
|
||||
|
||||
1. `onHide` - 场景隐藏时执行(如果当前显示)
|
||||
2. `onDestory` - 场景销毁时执行(一次)
|
||||
|
||||
## 实际应用示例
|
||||
|
||||
以下是一个完整的生命周期应用示例:
|
||||
|
||||
### scenes/dashboard/index.pe
|
||||
|
||||
```html
|
||||
<sence>
|
||||
<box class="dashboard">
|
||||
<text class="title">仪表板</text>
|
||||
<text class="status">状态: {{ status }}</text>
|
||||
<text class="last-update">最后更新: {{ lastUpdate }}</text>
|
||||
|
||||
<box class="data-container">
|
||||
<box for="{item} in dataItems" class="data-card">
|
||||
<text class="card-title">{{ item.title }}</text>
|
||||
<text class="card-value">{{ item.value }}</text>
|
||||
</box>
|
||||
</box>
|
||||
|
||||
<box class="controls">
|
||||
<box class="btn btn-primary" @click="refreshData">刷新数据</box>
|
||||
<box class="btn btn-secondary" @click="PE.navigateTo('/settings')">设置</box>
|
||||
</box>
|
||||
</box>
|
||||
</sence>
|
||||
|
||||
<script>
|
||||
// 数据状态
|
||||
let status = '加载中...'
|
||||
let lastUpdate = ''
|
||||
let dataItems = []
|
||||
let refreshTimer = null
|
||||
let dataRefreshInterval = null
|
||||
|
||||
// onLoad - 只执行一次
|
||||
onLoad(() => {
|
||||
console.log('仪表板加载')
|
||||
|
||||
// 初始化数据
|
||||
initializeData()
|
||||
|
||||
// 设置全局事件监听器
|
||||
setupEventListeners()
|
||||
|
||||
// 加载初始数据
|
||||
loadData()
|
||||
})
|
||||
|
||||
// onShow - 每次显示时执行
|
||||
onShow(() => {
|
||||
console.log('仪表板显示')
|
||||
|
||||
// 更新状态
|
||||
updateStatus('运行中')
|
||||
|
||||
// 启动定时刷新
|
||||
startAutoRefresh()
|
||||
|
||||
// 恢复动画
|
||||
resumeAnimations()
|
||||
})
|
||||
|
||||
// onHide - 隐藏时执行
|
||||
onHide(() => {
|
||||
console.log('仪表板隐藏')
|
||||
|
||||
// 暂停自动刷新
|
||||
stopAutoRefresh()
|
||||
|
||||
// 暂停动画
|
||||
pauseAnimations()
|
||||
|
||||
// 保存当前状态
|
||||
saveCurrentState()
|
||||
})
|
||||
|
||||
// onDestory - 销毁时执行
|
||||
onDestory(() => {
|
||||
console.log('仪表板销毁')
|
||||
|
||||
// 清理所有资源
|
||||
cleanup()
|
||||
})
|
||||
|
||||
// 初始化数据
|
||||
function initializeData() {
|
||||
dataItems = [
|
||||
{ title: '用户数', value: '0' },
|
||||
{ title: '订单数', value: '0' },
|
||||
{ title: '收入', value: '¥0' }
|
||||
]
|
||||
|
||||
updateUI()
|
||||
}
|
||||
|
||||
// 设置事件监听器
|
||||
function setupEventListeners() {
|
||||
// 监听网络状态变化
|
||||
window.addEventListener('online', handleOnline)
|
||||
window.addEventListener('offline', handleOffline)
|
||||
}
|
||||
|
||||
// 加载数据
|
||||
async function loadData() {
|
||||
try {
|
||||
updateStatus('加载数据中...')
|
||||
|
||||
// 模拟API调用
|
||||
const data = await fetchDataFromAPI()
|
||||
|
||||
dataItems = data
|
||||
lastUpdate = new Date().toLocaleString()
|
||||
|
||||
updateStatus('数据加载完成')
|
||||
updateUI()
|
||||
} catch (error) {
|
||||
console.error('加载数据失败:', error)
|
||||
updateStatus('数据加载失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 模拟API调用
|
||||
function fetchDataFromAPI() {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve([
|
||||
{ title: '用户数', value: Math.floor(Math.random() * 1000) },
|
||||
{ title: '订单数', value: Math.floor(Math.random() * 500) },
|
||||
{ title: '收入', value: '¥' + (Math.random() * 10000).toFixed(2) }
|
||||
])
|
||||
}, 1000)
|
||||
})
|
||||
}
|
||||
|
||||
// 启动自动刷新
|
||||
function startAutoRefresh() {
|
||||
if (dataRefreshInterval) {
|
||||
clearInterval(dataRefreshInterval)
|
||||
}
|
||||
|
||||
dataRefreshInterval = setInterval(() => {
|
||||
loadData()
|
||||
}, 30000) // 每30秒刷新一次
|
||||
|
||||
// 启动更新时间戳定时器
|
||||
if (refreshTimer) {
|
||||
clearInterval(refreshTimer)
|
||||
}
|
||||
|
||||
refreshTimer = setInterval(() => {
|
||||
updateTimestamp()
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
// 停止自动刷新
|
||||
function stopAutoRefresh() {
|
||||
if (dataRefreshInterval) {
|
||||
clearInterval(dataRefreshInterval)
|
||||
dataRefreshInterval = null
|
||||
}
|
||||
|
||||
if (refreshTimer) {
|
||||
clearInterval(refreshTimer)
|
||||
refreshTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
// 更新状态显示
|
||||
function updateStatus(newStatus) {
|
||||
status = newStatus
|
||||
const statusElement = game.getSceneElement('status')
|
||||
if (statusElement) {
|
||||
statusElement.element.textContent = `状态: ${status}`
|
||||
}
|
||||
}
|
||||
|
||||
// 更新时间戳显示
|
||||
function updateTimestamp() {
|
||||
if (lastUpdate) {
|
||||
const timeElement = game.getSceneElement('last-update')
|
||||
if (timeElement) {
|
||||
const elapsed = Math.floor((new Date() - new Date(lastUpdate)) / 1000)
|
||||
timeElement.element.textContent = `最后更新: ${lastUpdate} (${elapsed}秒前)`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新UI
|
||||
function updateUI() {
|
||||
// 更新数据卡片
|
||||
const container = game.getSceneElement('data-container')
|
||||
if (container) {
|
||||
// 清空现有内容
|
||||
container.element.innerHTML = ''
|
||||
|
||||
// 添加新的数据卡片
|
||||
dataItems.forEach(item => {
|
||||
const card = document.createElement('div')
|
||||
card.className = 'data-card'
|
||||
card.innerHTML = `
|
||||
<div class="card-title">${item.title}</div>
|
||||
<div class="card-value">${item.value}</div>
|
||||
`
|
||||
container.element.appendChild(card)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 刷新数据
|
||||
function refreshData() {
|
||||
loadData()
|
||||
}
|
||||
|
||||
// 处理在线状态
|
||||
function handleOnline() {
|
||||
updateStatus('在线')
|
||||
}
|
||||
|
||||
// 处理离线状态
|
||||
function handleOffline() {
|
||||
updateStatus('离线')
|
||||
}
|
||||
|
||||
// 恢复动画
|
||||
function resumeAnimations() {
|
||||
console.log('恢复动画')
|
||||
}
|
||||
|
||||
// 暂停动画
|
||||
function pauseAnimations() {
|
||||
console.log('暂停动画')
|
||||
}
|
||||
|
||||
// 保存当前状态
|
||||
function saveCurrentState() {
|
||||
console.log('保存当前状态')
|
||||
}
|
||||
|
||||
// 清理资源
|
||||
function cleanup() {
|
||||
// 停止所有定时器
|
||||
stopAutoRefresh()
|
||||
|
||||
// 移除事件监听器
|
||||
window.removeEventListener('online', handleOnline)
|
||||
window.removeEventListener('offline', handleOffline)
|
||||
|
||||
// 清理数据
|
||||
dataItems = []
|
||||
status = ''
|
||||
lastUpdate = ''
|
||||
|
||||
console.log('资源清理完成')
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
## 生命周期最佳实践
|
||||
|
||||
### 1. 合理分配操作到不同钩子
|
||||
|
||||
```javascript
|
||||
// 正确的做法
|
||||
onLoad(() => {
|
||||
// 一次性初始化操作
|
||||
initializeDatabase()
|
||||
setupGlobalEventListeners()
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
// 每次显示时的操作
|
||||
startDataPolling()
|
||||
resumeAnimations()
|
||||
})
|
||||
|
||||
onHide(() => {
|
||||
// 隐藏时的操作
|
||||
stopDataPolling()
|
||||
pauseAnimations()
|
||||
})
|
||||
|
||||
onDestory(() => {
|
||||
// 销毁时的操作
|
||||
cleanupResources()
|
||||
removeEventListeners()
|
||||
})
|
||||
```
|
||||
|
||||
### 2. 及时清理资源
|
||||
|
||||
```javascript
|
||||
onLoad(() => {
|
||||
// 创建定时器
|
||||
this.timer = setInterval(updateData, 5000)
|
||||
|
||||
// 添加事件监听器
|
||||
document.addEventListener('keydown', handleKeyDown)
|
||||
})
|
||||
|
||||
onDestory(() => {
|
||||
// 清理定时器
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer)
|
||||
this.timer = null
|
||||
}
|
||||
|
||||
// 移除事件监听器
|
||||
document.removeEventListener('keydown', handleKeyDown)
|
||||
})
|
||||
```
|
||||
|
||||
### 3. 处理异步操作
|
||||
|
||||
```javascript
|
||||
onLoad(async () => {
|
||||
try {
|
||||
// 异步加载数据
|
||||
this.data = await loadDataFromServer()
|
||||
updateUI()
|
||||
} catch (error) {
|
||||
console.error('加载数据失败:', error)
|
||||
showErrorMessage()
|
||||
}
|
||||
})
|
||||
|
||||
onDestory(() => {
|
||||
// 取消未完成的请求
|
||||
if (this.currentRequest) {
|
||||
this.currentRequest.cancel()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
通过以上内容,你已经了解了PE引擎的生命周期机制。这些生命周期钩子为你提供了强大的控制能力,让你能够精确管理场景的创建、显示、隐藏和销毁过程。
|
||||
Reference in New Issue
Block a user