Discord.js实现表情反应切换帮助命令分页功能的问题咨询
Discord翻页式帮助命令代码修复方案
原有代码的核心问题
- 引用对象错误:代码中写的
message.reaction.id不存在,实际需要判断触发事件的反应所属消息ID,应该用reaction.message.id - 变量作用域错误:
msg2只在第一个if分支内定义,第二个else if分支无法访问该变量 - 监听器重复注册:每次执行
execute函数都会给client新增一个全局的messageReactionAdd监听器,多次调用后会出现重复触发、内存泄漏问题 - 缺少过滤逻辑:没有判断用户点击的表情是否为翻页箭头,也没有过滤无关消息的反应,其他消息的互动也会误触发逻辑
推荐修复方案(编辑消息实现,体验更流畅)
不需要删除原有消息重发,直接修改消息内容即可实现翻页效果,性能和用户体验更好:
async execute(message, client){ // 提前定义所有分页内容,后续新增分页直接加在这里即可 const pages = [ 'how are', 'you?' ] // 定义翻页对应表情 const prevEmoji = '◀' const nextEmoji = '▶' let currentPage = 0 // 发送第一页内容 const pageMsg = await message.channel.send(pages[currentPage]) // 有多页时才添加下一页反应 if (pages.length > 1) await pageMsg.react(nextEmoji) // 配置反应过滤器:仅允许触发命令的用户点击翻页箭头才生效 const filter = (reaction, user) => { return !user.bot && [prevEmoji, nextEmoji].includes(reaction.emoji.name) && reaction.message.id === pageMsg.id && user.id === message.author.id } // 创建临时反应收集器,10分钟无操作自动销毁避免内存泄漏 const collector = pageMsg.createReactionCollector({ filter, time: 10 * 60 * 1000 }) collector.on('collect', async (reaction, user) => { // 移除用户的点击痕迹,方便用户后续重复点击 await reaction.users.remove(user.id) // 切换页码 if (reaction.emoji.name === nextEmoji && currentPage < pages.length - 1) { currentPage++ } else if (reaction.emoji.name === prevEmoji && currentPage > 0) { currentPage-- } // 直接编辑消息内容更新分页 await pageMsg.edit(pages[currentPage]) // 调整显示的反应:第一页不显示上一页箭头,最后一页不显示下一页箭头 if (currentPage === 0) { await pageMsg.reactions.cache.get(prevEmoji)?.remove() if (!pageMsg.reactions.cache.has(nextEmoji)) await pageMsg.react(nextEmoji) } else if (currentPage === pages.length - 1) { await pageMsg.reactions.cache.get(nextEmoji)?.remove() if (!pageMsg.reactions.cache.has(prevEmoji)) await pageMsg.react(prevEmoji) } else { if (!pageMsg.reactions.cache.has(prevEmoji)) await pageMsg.react(prevEmoji) if (!pageMsg.reactions.cache.has(nextEmoji)) await pageMsg.react(nextEmoji) } }) // 收集器到期后移除所有反应,提示翻页已失效 collector.on('end', () => { pageMsg.reactions.removeAll().catch(() => {}) }) }
兼容原删除重发逻辑的修复版本
如果你要保留原有删除旧消息、发新消息的逻辑,可以使用下面的修复版本:
async execute(message, client){ let currentMsg = await message.channel.send('how are') await currentMsg.react('▶') const filter = (reaction, user) => { return !user.bot && ['◀', '▶'].includes(reaction.emoji.name) && reaction.message.id === currentMsg.id && user.id === message.author.id } const collector = currentMsg.createReactionCollector({ filter, time: 10 * 60 * 1000 }) collector.on('collect', async () => { await currentMsg.delete() // 判断当前显示的是第一页还是第二页,切换到对应内容 if (currentMsg.content === 'how are') { currentMsg = await message.channel.send('you?') await currentMsg.react('◀') } else { currentMsg = await message.channel.send('how are') await currentMsg.react('▶') } // 更新过滤器监听的消息ID collector.filter = (reaction, user) => { return !user.bot && ['◀', '▶'].includes(reaction.emoji.name) && reaction.message.id === currentMsg.id && user.id === message.author.id } }) }
内容的提问来源于stack exchange,提问作者Joaquin Parada
相关产品推荐
相关产品推荐

