如何在点击元素与页面加载时触发函数并保留$(this)选择器
问题描述
在基于Liferay 7.4的自定义片段中,有一组带自定义ID的可展开折叠面板(Accordion),需实现两个功能:
- 点击标题时控制对应面板的展开/收起
- URL带有锚点时,自动展开对应ID的面板
已实现点击标题的逻辑,代码如下:
$('.accordion-heading').on('click',toggleOpen); function toggleOpen(){ if( $(this).attr('aria-expanded') == 'false' ) { $(this).attr('aria-expanded','true'); $(this).next().removeClass('hide'); } else if( $(this).attr('aria-expanded') == 'true' ) { $(this).attr('aria-expanded','false'); $(this).next().addClass('hide'); } }
点击时$(this)选择器工作正常。但处理URL锚点逻辑时,无法对找到的目标.accordion-heading元素执行toggleOpen函数并保留原有逻辑,锚点处理的现有代码:
const targetAnchor = $(location).attr('hash'); const thisAnchor = configuration.anchor; // 从片段配置获取的字符串值 if( (targetAnchor.replace('#','')) == thisAnchor) { let thisAccordionHeading = $(targetAnchor).find('.accordion-heading'); console.log($(thisAccordionHeading)); // 已确认能正确找到目标元素 // ---- 需要在这里执行toggleOpen函数处理该元素 }
解决方案
1. 改造toggleOpen函数,支持手动传入元素
原函数依赖事件上下文this,修改为接受可选元素参数,让函数兼容事件触发和手动调用两种场景:
function toggleOpen(element) { // 优先使用传入的元素,无传入则用事件触发的this const $heading = element ? $(element) : $(this); const isExpanded = $heading.attr('aria-expanded') === 'true'; if (!isExpanded) { $heading.attr('aria-expanded', 'true'); $heading.next().removeClass('hide'); } else { $heading.attr('aria-expanded', 'false'); $heading.next().addClass('hide'); } } // 原有点击事件绑定保持不变 $('.accordion-heading').on('click', toggleOpen);
2. 在锚点逻辑中调用改造后的函数
找到目标元素后,直接将其传入toggleOpen即可触发对应逻辑:
const targetAnchor = $(location).attr('hash'); const thisAnchor = configuration.anchor; if (targetAnchor.replace('#', '') === thisAnchor) { const $targetHeading = $(targetAnchor).find('.accordion-heading'); // 确保元素存在再执行操作 if ($targetHeading.length > 0) { // 可选:仅当面板处于收起状态时触发展开,避免重复切换 if ($targetHeading.attr('aria-expanded') === 'false') { toggleOpen($targetHeading[0]); } } }
额外优化点
- 可将锚点检测逻辑放在页面
load事件中,确保页面初始化时就自动展开对应面板 - 若需同时收起其他面板,可在触发目标面板展开前,遍历所有
.accordion-heading执行收起操作
内容的提问来源于stack exchange,提问作者Luca Detomi
相关产品推荐
相关产品推荐

