基于eventListener与cookie设置的滚动触发modal开发问题求助
现有代码问题
- 未提前校验cookie状态就绑定scroll事件,无效监听占用性能
set_cookie方法中过期时间属性错误,错误使用time字段,正确的有效期字段应为max-age,导致cookie无法按预期30天过期- 未按登录状态区分逻辑,所有用户都统一走cookie校验逻辑,不符合需求
- scroll事件未做防抖处理,滚动过程中会高频触发视口检测逻辑,产生不必要的性能消耗
- 弹窗触发后未移除scroll监听,后续滚动仍会重复执行检测逻辑,可能导致弹窗重复触发
优化后完整实现代码
$(document).ready(function () { const element = document.querySelector('.modalElement'); if (!element) return; const modal_target = element.getAttribute('data-target'); const user_logged_in = document.body.classList.contains('logged-in'); const stored_cookie = get_cookie('acceptedPardot' + modal_target + 'Cookie'); // 未登录且已有cookie,直接不绑定scroll监听 if (!user_logged_in && stored_cookie) return; // 防抖函数,降低scroll触发频率 function debounce(func, wait) { let timeout; return function() { clearTimeout(timeout); timeout = setTimeout(func, wait); } } // scroll处理逻辑 function scrollHandler() { if (is_in_viewport(element)) { trigger_modal(element); } } // 绑定带防抖的scroll监听 const debouncedScroll = debounce(scrollHandler, 300); window.addEventListener("scroll", debouncedScroll); /** * Trigger modal * * @param element */ function trigger_modal(element) { // 已登录用户直接弹弹窗,不操作cookie if (user_logged_in) { $(modal_target).modal('toggle'); return; } // 未登录用户走cookie逻辑 if (!stored_cookie) { set_cookie('acceptedPardot' + modal_target + 'Cookie', 'true', 30); $(modal_target).modal('toggle'); // 触发后移除scroll监听,避免重复触发 window.removeEventListener('scroll', debouncedScroll); } } /** * Set cookie * * @param name * @param value * @param days * @return {string} */ function set_cookie(name, value, days) { let cookie = name + "=" + encodeURIComponent(value); if (typeof days === "number") { // 修复过期时间字段,新增path配置保证全站生效 cookie += "; max-age=" + (days * 24 * 60 * 60) + "; path=/"; document.cookie = cookie; return cookie; } } /** * Get cookie * * @param name * @return {string|null} */ function get_cookie(name) { let cookie_array = document.cookie.split(";"); for (let i = 0; i < cookie_array.length; i++) { const cookie_pair = cookie_array[i].split("="); if (name === cookie_pair[0].trim()) { return decodeURIComponent(cookie_pair[1]); } } return null; } /** * Check if element is in viewport * * @param element * @return {boolean} */ function is_in_viewport(element) { const rect = element.getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth) ); } });
内容的提问来源于stack exchange,提问作者user16645285
相关产品推荐
相关产品推荐

