使用Element UI el-pagination时this.$root为undefined问题排查
报错原因
- 你绑定事件时用了普通
function声明回调,这种写法下函数内部的this指向触发事件的DOM元素(也就是页码<li>节点),不是Vue组件实例,自然访问不到$root属性。 - 逻辑层面也有问题:
CurrentChange方法是定义在各个引入分页的业务组件内部的,并没有挂载到Vue根实例上,就算你拿到了$root,调用这个方法依然会报找不到的错误。 - 实现方式存在隐患:直接通过
document.querySelectorAll全局查找DOM绑定事件,会出现事件重复绑定、分页动态重渲染后事件失效、组件销毁后事件不卸载造成内存泄漏的问题,另外Element UI默认的页码按钮没有设置tabindex,键盘根本无法聚焦,就算事件绑对了也触发不了。
修复方案
不要直接全局操作DOM绑定原生事件,在mixin内基于当前组件实例做事件绑定,逻辑和Vue生命周期对齐,实现如下:
- 调整pagination.js mixin代码:
export default { mounted() { this.$nextTick(() => { this.bindPaginationKeyEvent() }) // 监听总条数变化,分页重渲染后重新绑定事件 this.$watch('getTotal', () => { this.$nextTick(() => { this.bindPaginationKeyEvent() }) }) }, methods: { bindPaginationKeyEvent() { // 先解绑旧事件,避免重复绑定 if (this._paginationKeyHandler) { this.$el.removeEventListener('keyup', this._paginationKeyHandler) } // 用事件委托,把事件绑在当前组件根节点,不用逐个遍历li this._paginationKeyHandler = (e) => { const target = e.target // 校验触发事件的是页码按钮 if ( target.tagName === 'LI' && target.classList.contains('number') && target.parentElement?.classList.contains('el-pager') ) { // 兼容回车、空格两种触发键 if (e.key === 'Enter' || e.code === 'Space') { const targetPage = Number(target.textContent.trim()) // 更新当前页码,和原有逻辑对齐 this.currentPage = targetPage // 如果业务组件自定义了CurrentChange逻辑,直接调用 if (typeof this.CurrentChange === 'function') { this.CurrentChange(targetPage) } } } } this.$el.addEventListener('keyup', this._paginationKeyHandler) // 给页码按钮加tabindex,支持键盘聚焦 this.$el.querySelectorAll('ul.el-pager li.number').forEach(item => { item.setAttribute('tabindex', '0') }) } }, beforeDestroy() { // 组件销毁时移除事件,避免内存泄漏 if (this._paginationKeyHandler) { this.$el.removeEventListener('keyup', this._paginationKeyHandler) } } }
- 业务组件里正常引入这个mixin即可,原有el-pagination的模板代码、
CurrentChange方法都不需要改动,就能实现键盘回车/空格触发页码跳转。
注意:要保证使用mixin的业务组件内定义了
currentPage、getTotal这两个和分页绑定的响应式字段,和你原来的写法保持一致即可。
内容的提问来源于stack exchange,提问作者Neeza
相关产品推荐
相关产品推荐

