You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

按键监听实现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%");
                }
            }
        });
        
    }
    
}

问题根源

  1. generateToast函数逻辑错误:调用generateToast({show:'none'})时,会新增一个隐藏的Toast元素,而非关闭已存在的Toast,导致实例不断堆积。
  2. 缺少活跃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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 14:27:16