类内onclick调用类方法提示未定义的解决方法及addEventListener替代方案咨询
类内onclick调用类方法提示未定义的解决方法及addEventListener替代方案
嘿,我完全懂你遇到的困扰——在类的handlePagination方法里用字符串拼接的onclick绑定函数时,总是提示方法未定义对吧?这可不是你的代码写错了,而是onclick里的代码是在全局作用域执行的,但你的handlePagination是Pagination类的实例方法,只属于每个创建出来的实例,不在全局范围内,自然找不到啦。
下面给你两种解决思路,其中第二种是更符合现代JS实践的推荐方案:
一、如果坚持要用innerHTML+onclick的方式(不推荐,但可实现)
我们可以把类实例挂载到对应的DOM元素上,让onclick代码能通过DOM元素找到实例方法:
- 首先在类的
constructor里,把当前实例绑定到pagination元素的自定义属性上:
constructor(pagination) { this.pagination = pagination; // 将实例挂载到DOM元素,方便后续调用 this.pagination._paginationInstance = this; this.ul = this.pagination.querySelector('.pagination > ul'); this.items = this.pagination.querySelectorAll('.post'); this.handlePagination(6, 1); }
- 然后修改
handlePagination里的onclick拼接代码,通过DOM元素找到实例并调用方法:
// 上一页按钮 li += `<li class="page-item page-prev ${currentPage <= 1 ? 'hidden' : ''}" onclick="this.closest('.pagination-block')._paginationInstance.handlePagination(${postPerPage}, ${currentPage - 1})"><span class="icon"><</span></li>`; // 页码按钮 li += `<li class="page-item ${currentPage == pageNumber ? ' active' : ''}" onclick="this.closest('.pagination-block')._paginationInstance.handlePagination(${postPerPage}, ${pageNumber})">${pageNumber}</li>`; // 下一页按钮 li += `<li class="page-item page-next ${currentPage >= totalPages ? 'hidden' : ''}" onclick="this.closest('.pagination-block')._paginationInstance.handlePagination(${postPerPage}, ${currentPage + 1})"><span class="icon">></span></li>`;
这种方式能解决问题,但依赖DOM结构,还存在一定的XSS风险,所以更推荐下面的方案。
二、推荐:改用创建DOM元素+addEventListener绑定事件
这种方式不仅能彻底解决this指向问题,代码也更清晰、更健壮,还能避免innerHTML的潜在风险。重写你的handlePagination方法如下:
handlePagination(postPerPage, currentPage) { this.updateCurrentPage(postPerPage, currentPage); const totalPages = Math.ceil(this.items.length / postPerPage); const pageNumbers = this.generatePageNumber(totalPages, currentPage); // 先清空分页列表 this.ul.innerHTML = ''; // 1. 创建上一页按钮 const prevLi = document.createElement('li'); prevLi.className = `page-item page-prev ${currentPage <= 1 ? 'hidden' : ''}`; prevLi.innerHTML = '<span class="icon"><</span>'; prevLi.addEventListener('click', () => { if (currentPage > 1) { this.handlePagination(postPerPage, currentPage - 1); } }); this.ul.appendChild(prevLi); // 2. 创建页码按钮 pageNumbers.forEach(pageNumber => { const li = document.createElement('li'); li.className = `page-item ${currentPage === pageNumber ? 'active' : ''}`; // 处理省略号,不能点击 if (pageNumber === '...') { li.textContent = '...'; li.style.cursor = 'default'; } else { li.textContent = pageNumber; // 绑定点击事件,箭头函数自动保留类实例的this指向 li.addEventListener('click', () => { this.handlePagination(postPerPage, pageNumber); }); } this.ul.appendChild(li); }); // 3. 创建下一页按钮 const nextLi = document.createElement('li'); nextLi.className = `page-item page-next ${currentPage >= totalPages ? 'hidden' : ''}`; nextLi.innerHTML = '<span class="icon">></span>'; nextLi.addEventListener('click', () => { if (currentPage < totalPages) { this.handlePagination(postPerPage, currentPage + 1); } }); this.ul.appendChild(nextLi); }
这个方案的优势:
- 箭头函数自动绑定了类实例的
this,调用this.handlePagination时不会出现指向错误; - 不用依赖全局作用域,代码封装性更好;
- 避免了innerHTML拼接字符串的繁琐和潜在安全问题;
- 逻辑拆分更清晰,后续维护和修改都更方便。
你可以直接把这段代码替换掉原来的handlePagination方法,测试一下,分页功能应该就能正常工作啦!
内容来源于stack exchange
相关产品推荐
相关产品推荐

