按键监听实现Toast消息自动关闭功能故障排查
姓名查询应用Toast交互问题解决思路
问题背景
开发姓名查询应用,输入名/姓后:
- 查询到匹配用户时返回对应数据
- 无匹配结果时弹出Toast提示“Unable to find the name you are searching for”,默认5秒后消失
需求修改:Toast弹出后,用户继续按键时立即关闭该Toast;若用户停止输入,Toast仍保持5秒后自动关闭的逻辑。
当前问题:为输入框添加keydown事件监听器调用generateToast({show:'none'})后,Toast未消失且不断生成新实例,将监听器移入nameinput函数也未得到预期效果。
现有代码
var nurl="https://www.example.com/rest/5/query"; var gurl="https://www.example.com/rest/3/query"; var nameA=[]; var dt1; var dt2; var dataA; var fnmarker; var lnmarker; var yposition; var mrkr; var ky; var postreturn = $.post(); const toastContainer = document.querySelector('.toast-container'); const fNameInput = document.getElementById('fnameTB'); const lNameInput = document.getElementById('lnameTB'); fNameInput.addEventListener('keydown', (e) => { if(e.key) { console.log('value of fnameinput ' + e.key); generateToast({show:'none'}); } }) lNameInput.addEventListener('keydown' , (e) => { if(e.key) { console.log("value of lnameinput " + e.key); generateToast({show:'none'}); } }); function generateToast ({message, show}) { toastContainer.insertAdjacentHTML('beforeend', `<p class='toast' style = 'display: ${show}'>${message}</p>`) const toast = toastContainer.lastElementChild; toast.addEventListener('animationend', () => { toast.remove() }) } $(function(){ window.scrollTo(0,yposition); addlayer(); }); function nameinput(){ $("#nameresults").html(""); postreturn.abort(); //abort ajax call if($("#lnameTB").val().length>2 || $("#fnameTB").val().length>2){ var nm="name like '"+$("#lnameTB").val()+"%' and name like '%, "+$("#fnameTB").val()+"%'"; postreturn=$.post(nurl,{where:nm,returnGeometry:false,f:"pjson",outFields:"*"},function(data){ nameA=$.parseJSON(data); if(nameA.features.length<1){ generateToast({message:'Unable to find the name you are searching for', show: 'inline'}); }else{ for(var i=0;i<nameA.features.length;i++){ $("#nameresults").append("<center><div class='d1' onclick='locateGrave("+i+")'>"+nameA.features[i].attributes.Name+"</div><div id='infodiv"+i+"' class='d2' onclick='closeinfo()'></div></center>"); } if(window.innerHeight<$("#nameresults").height()){ $("#cover").css("height",$("#nameresults").height()+50+"px"); }else{ $("#cover").css("height","100%"); } } }); } }
问题根源
generateToast函数逻辑错误:调用generateToast({show:'none'})时,会新增一个隐藏的Toast元素,而非关闭已存在的Toast,导致实例不断堆积。- 缺少活跃Toast跟踪:没有变量记录当前显示的Toast实例,无法直接对其执行关闭操作。
解决代码修改
1. 添加全局变量跟踪活跃Toast
在代码顶部变量声明区添加:
let activeToast = null; // 记录当前显示的Toast实例
2. 重构generateToast函数
修改为自动管理Toast实例,包含自动关闭逻辑:
function generateToast({ message }) { // 先清除已存在的Toast if (activeToast) { activeToast.remove(); activeToast = null; } // 创建新Toast toastContainer.insertAdjacentHTML('beforeend', `<p class='toast' style='display: inline'>${message}</p>`); activeToast = toastContainer.lastElementChild; // 5秒后自动关闭 const autoCloseTimer = setTimeout(() => { if (activeToast) { activeToast.remove(); activeToast = null; } }, 5000); // 动画结束后清理定时器和实例 activeToast.addEventListener('animationend', () => { clearTimeout(autoCloseTimer); activeToast = null; }); }
3. 修改按键事件监听器
直接关闭活跃Toast,不再调用错误的generateToast:
fNameInput.addEventListener('keydown', () => { if (activeToast) { activeToast.remove(); activeToast = null; } }); lNameInput.addEventListener('keydown', () => { if (activeToast) { activeToast.remove(); activeToast = null; } });
4. 调整nameinput中的Toast调用
原调用处简化为:
generateToast({message:'Unable to find the name you are searching for'});
额外优化建议
- 输入防抖:添加防抖函数,用户停止输入后再触发查询,避免频繁请求和Toast闪烁:
let debounceTimer; function nameinput(){ clearTimeout(debounceTimer); debounceTimer = setTimeout(() => { // 原nameinput逻辑 }, 300); // 300ms延迟,可根据需求调整 } - Toast动画:为
.toast类添加CSS过渡动画,提升交互体验:.toast { transition: opacity 0.3s ease; opacity: 1; } .toast.hidden { opacity: 0; pointer-events: none; }
内容的提问来源于stack exchange,提问作者zanzibar
相关产品推荐
相关产品推荐

