一、什么是 destroyed 钩子
`destroyed` 是 Vue.js (以及基于 Vue 的 Uniapp) 组件生命周期中的一个重要钩子函数,它会在 Vue/Uniapp 实例被销毁后调用。在 Uniapp 中,这个生命周期函数同样适用,当页面或组件被卸载时触发。
二、destroyed 的执行时机
`destroyed` 钩子在以下情况下会被调用:
1. 页面导航离开时:当用户从当前页面跳转到其他页面(非 tabbar 页面)
2. 组件被移除时:当父组件动态移除了某个子组件
3. 手动销毁实例时:通过调用 `this.$destroy()`
需要注意的是:
- tabbar切换不会触发页面的 `destroyed`
- `navigateBack`返回时会触发前一个页面的 `created`,但不会立即销毁当前页
三、基本用法示例
javascript
export default {
data() {
return {
timer: null
}
},
created() {
//创建一个定时器
this.timer = setInterval(() => {
console.log('定时器运行中...')
},1000)
},
destroyed() {
//清除定时器避免内存泄漏
if(this.timer) {
clearInterval(this.timer)
this.timer = null;
console.log('定时器已清除')
}
console.log('组件/页面已被销毁')
}
}
四、实际应用场景
1.清理工作
javascript
destroyed() {
//取消事件监听
uni.$off('someEvent', this.handleEvent);
//清除地图实例
if(this.map) {
this.map.destroy();
this.map = null;
}
}
2.数据保存到全局或缓存
javascript
destoryed() {
//将表单数据保存到全局store或缓存
if(this.formData) {
uni.setStorageSync('draftForm',this.formData);
}
//或者使用vuex
this.$store.commit('saveTempData',this.tempData);
}
3.WebSocket连接关闭
javascript
destoryed(){
if(this.socket && this.socket.readyState === WebSocket.OPEN){
this.socket.close();
console.log("WebSocket连接已关闭");
}
}
五、注意事项与最佳实践
1.与 beforeDestroy的区别
- `beforeDestroy`:实例销毁之前调用,此时实例仍然完全可用(适合做清理前的准备工作)
- `destoryed`:实例销毁后调用,所有绑定和监听都会被移除,子实例也都被销毁
2.移动端特殊考虑
在Uniapp的移动端环境中:
- Android物理返回键会触发destoryed而iOS滑动返回默认不会(可通过配置改变)
- APP进入后台不会触发,destory只在实际卸载时发生
3.性能优化建议
对于可能频繁创建销毁的组件:
- destory时要彻底释放大对象引用(null赋值)
- WebGL/Canvas等资源要手动释放
4.常见错误处理
javascript
destoryd(){
try{
this.clearAllIntervals();
}catch(e){
console.error("清理失败:",e);
}
},
methods:{
clearAllIntervals(){
let lastId = setInterval(()=>{},9999);
for(let i=lastId;i>=0;i--){
clearInterval(i);
}
}
}
5.调试技巧
可以在控制台输出查看是否发生内存泄漏:
//在入口文件添加
Vue.config.devtools=true;
Vue.config.debug=true;
Vue.config.productionTip=false;
六、总结
合理使用 destoryd生命周期能有效防止:
✓内存泄漏 ✓事件堆积 ✓资源未释放等问题。在Uniapp开发中,特别是需要管理原生资源的场景(如地图、音视频),做好销毁处理尤为重要。
文章点评