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

如何通过Svelte Context配置手风琴默认展开及跳转联动功能?

帮助中心FAQ手风琴组件优化方案

问题背景

当前帮助中心FAQ使用的手风琴组件默认全部关闭,需要实现两个核心需求:

  • 通过Svelte Context配置,页面加载时指定手风琴默认展开,保留原有交互功能;
  • 从网站其他页面跳转至帮助中心时,自动展开目标手风琴及其子菜单。

第一步:修改Accordion.svelte,增强Context与路由匹配能力

给组件添加id属性,通过Context管理展开状态集合,同时监听URL哈希实现跳转自动展开:

<script context="module">
import { setContext, getContext } from 'svelte';
import { writable } from 'svelte/store';

const key = {};

export const getAccordionContext = () => getContext(key);
export const createAccordionContext = (defaultOpenIds = []) => {
    // 存储当前展开的手风琴ID集合,支持多展开(单一展开可改为存储单个值)
    const openIds = writable(new Set(defaultOpenIds));
    // 监听URL哈希变化
    const urlHash = writable(window.location.hash.slice(1));

    window.addEventListener('hashchange', () => {
        urlHash.set(window.location.hash.slice(1));
    });

    const context = { openIds, urlHash };
    setContext(key, context);
    
    return context;
}
</script>
<script>
import { quadInOut } from 'svelte/easing';
import { slide } from 'svelte/transition';
import { onMount } from 'svelte';

export let id = '';
export let open = false;

const { openIds, urlHash } = getAccordionContext();
// 子级重新创建Context,避免与父级状态冲突
createAccordionContext();

// 点击切换展开/关闭状态
function handleClick() {
    $openIds = new Set($openIds);
    if ($openIds.has(id)) {
        $openIds.delete(id);
        open = false;
    } else {
        // 若需单一展开模式,取消下方注释清空所有展开状态
        // $openIds.clear();
        $openIds.add(id);
        open = true;
    }
}

// 同步Context中的展开状态到当前组件
$: if ($openIds.has(id)) {
    open = true;
} else if (open) {
    open = false;
}

// 页面加载时匹配URL哈希展开目标手风琴
onMount(() => {
    if ($urlHash === id) {
        $openIds.add(id);
    }
});

// 监听哈希变化,实时展开对应组件
$: if ($urlHash === id && !$openIds.has(id)) {
    $openIds.add(id);
}
</script>

<div class="accordion">
  <div class="header" on:click={handleClick}>
      <div class="text">
          <slot name="head"></slot> 
      </div>
  </div>

  {#if open}
  <div class="details" transition:slide="{{ duration: 150, easing:quadInOut }}">
      <slot name="details"></slot>
  </div>
  {/if}
</div>

<style>
div.accordion {
    margin: 1rem 0;
}
div.header {
    display:flex;
    width:100%;
    cursor: pointer;
}
div.header .text {
    flex: 1;
}
div.details {
    background-color: transparent;
    padding:1rem;
}
</style>

第二步:修改App.svelte,配置默认展开与添加唯一ID

给每个手风琴添加唯一ID,同时在创建Context时传入默认展开的ID列表;跳转时只需在URL后拼接#目标ID即可自动展开:

<script>
import Accordion, { createAccordionContext } from "./Accordion.svelte"

// 配置默认展开的手风琴ID,支持多级嵌套
createAccordionContext(['faq-main-1', 'faq-sub-1'])
</script>

<Accordion id="faq-main-1">
    <div slot="head">
        <h2>Test one</h2>
    </div>
    <div slot="details">
        <ul>
            <Accordion id="faq-sub-1">
                <div slot="head">
                    <h4>The test of subitem?</h4>
                </div>
                <div slot="details">
                    <li>1</li>
                    <li>2</li>
                    <li>3</li>
                </div>
            </Accordion>

            <Accordion id="faq-sub-2">
                <div slot="head">
                    <h4>Test of subitem 2</h4>
                </div>
                <div slot="details">
                    <li>one</li>
                    <li>two</li>
                    <li>three</li>
                </div>
            </Accordion>
        </ul>
    </div>
</Accordion>

<Accordion id="faq-main-2">
    <div slot="head">
        <h4>Second test</h4>
    </div>
    <div slot="details">
        <ul>
            <li>again one</li>
            <li>two again</li>
            <li>three repeat</li>
        </ul>
    </div>
</Accordion>

<style>
li {
    margin: 0;
    padding: 1em;
    text-align: left;
    list-style-type: none;
    cursor: pointer;
    color: black;
}

h4, h2 {
    cursor: pointer;
}
</style>

功能说明

  1. 默认展开配置:通过createAccordionContext(['id1', 'id2'])传入需要默认展开的手风琴ID,页面加载时自动展开对应组件;
  2. 跳转自动展开:其他页面跳转时,使用带哈希的URL(如/help-center#faq-main-2),手风琴会自动匹配ID并展开;
  3. 保留原有交互:点击头部仍可切换展开/关闭状态,完全兼容原有操作逻辑;
  4. 展开模式可选:若需同一层级仅展开一个手风琴,取消handleClick中$openIds.clear()的注释即可。

内容的提问来源于stack exchange,提问作者Tomca z Brodku

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 01:50:50