# uniapp 封装监听watch

# 监听watch eg:聊天消息

你这个写法里用到了

uni.$on('notifyChatMessage', callback)
✅ Copy success!

它是全局事件监听,如果你不在页面销毁的时候移除,会造成重复监听或者内存泄漏

onUnloadonHide 里调用 uni.$off 就可以了。

完整写法如下:

export default {
	onLoad() {
		let that = this
		// 定义回调函数,方便移除监听时使用
		this._notifyChatHandler = function(data) {
			console.log('监听chat消息:', data)
			that.initListQuery()
		}

		this.$nextTick(() => {
			uni.$on('notifyChatMessage', this._notifyChatHandler)
		})
	},

	onUnload() {
		// 页面销毁时移除监听
		if (this._notifyChatHandler) {
			uni.$off('notifyChatMessage', this._notifyChatHandler)
		}
	},

	onHide() {
		// 如果你希望切到后台或返回也取消监听,可以在这里再加一层保险
		if (this._notifyChatHandler) {
			uni.$off('notifyChatMessage', this._notifyChatHandler)
		}
	},

	methods: {
		initListQuery() {
			// 你的刷新逻辑
		}
	}
}
✅ Copy success!

这样就不会出现页面返回后还在监听的情况了。

要不要我帮你改成一个通用的封装函数(比如 listenOnce 这种),在进入页面时监听,退出时自动销毁?

# ===============================v2版本

👍 我帮你封装一个 通用监听工具函数,可以做到:

  • 进入页面时自动监听
  • 离开页面(onUnloadonHide)时自动销毁
  • 不用每次手动写 $on/$off

# 封装工具 eventHelper.js

(放到 common/ 或者 utils/ 目录里)

// common/eventHelper.js
export function listenOnce(vm, eventName, callback, options = { autoOff: true }) {
	// 保存回调到组件实例,方便解绑
	if (!vm.__eventHandlers) {
		vm.__eventHandlers = {}
	}

	// 包装后的回调
	const handler = function (data) {
		callback && callback(data)
	}

	// 注册监听
	uni.$on(eventName, handler)
	vm.__eventHandlers[eventName] = handler

	// 自动销毁(onUnload/onHide)
	if (options.autoOff) {
		const offFn = () => {
			if (vm.__eventHandlers[eventName]) {
				uni.$off(eventName, vm.__eventHandlers[eventName])
				delete vm.__eventHandlers[eventName]
			}
		}

		// 原始生命周期函数
		const oldUnload = vm.onUnload
		const oldHide = vm.onHide

		vm.onUnload = function () {
			offFn()
			oldUnload && oldUnload.call(vm)
		}

		vm.onHide = function () {
			offFn()
			oldHide && oldHide.call(vm)
		}
	}

	return handler
}
✅ Copy success!

# 页面使用示例

<script>
import { listenOnce } from '@/common/eventHelper.js'

export default {
	onLoad() {
		listenOnce(this, 'notifyChatMessage', (data) => {
			console.log('收到chat消息:', data)
			this.initListQuery()
		})
	},
	methods: {
		initListQuery() {
			// 刷新逻辑
		}
	}
}
</script>
✅ Copy success!

这样写,页面退出后监听会自动解绑,不会重复。


要不要我再给你写一个 支持多事件批量监听 的版本?比如一行代码同时监听 notifyChatMessagenotifySystemMessage 等多个事件。