Skip to content

Commit 27de5b4

Browse files
committed
perf: 手机适配
1 parent bc9efc6 commit 27de5b4

1 file changed

Lines changed: 39 additions & 36 deletions

File tree

src/components/Navbar.astro

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Search from "./Search.svelte";
99
import DisplaySettings from "./widget/DisplaySettings.svelte";
1010
import DropdownMenu from "./widget/DropdownMenu.astro";
1111
import TranslateButton from "./widget/TranslateButton.svelte";
12+
import NavMenuPanel from "./widget/NavMenuPanel.astro";
1213
1314
const className = Astro.props.class;
1415
@@ -51,8 +52,12 @@ let links: NavBarLink[] = navBarConfig.links.map(
5152
<div class="hidden sm:block">
5253
<LightDarkSwitch client:only="svelte"></LightDarkSwitch>
5354
</div>
55+
<button aria-label="Menu" class="btn-plain scale-animation rounded-lg w-11 h-11 active:scale-90 md:hidden" id="nav-menu-switch">
56+
<Icon name="material-symbols:menu-rounded" class="text-[1.25rem]"></Icon>
57+
</button>
5458
</div>
5559
<DisplaySettings client:only="svelte"></DisplaySettings>
60+
<NavMenuPanel links={links}></NavMenuPanel>
5661
</div>
5762
</div>
5863

@@ -163,8 +168,7 @@ function closeAllDropdowns() {
163168

164169
function toggleDropdown(dropdown, trigger, menu) {
165170
const isOpen = trigger.getAttribute('aria-expanded') === 'true';
166-
if (isOpen) closeDropdown(dropdown, trigger, menu);
167-
else openDropdown(dropdown, trigger, menu);
171+
if (isOpen) closeDropdown(dropdown, trigger, menu); else openDropdown(dropdown, trigger, menu);
168172
}
169173
function openDropdown(dropdown, trigger, menu) {
170174
trigger.setAttribute('aria-expanded', 'true');
@@ -179,39 +183,33 @@ function closeDropdown(dropdown, trigger, menu) {
179183

180184
function bindDisplaySettings() {
181185
const btn = document.getElementById('display-settings-switch');
182-
if (!btn) return;
183-
184-
const attach = () => {
185-
if (btn.dataset.bound === '1') return;
186-
btn.addEventListener('click', () => {
187-
const panelEl = document.getElementById('display-setting');
188-
if (!panelEl) return;
189-
panelEl.classList.toggle('float-panel-closed');
190-
});
191-
btn.dataset.bound = '1';
192-
};
193-
194186
const panel = document.getElementById('display-setting');
195-
if (panel) {
196-
attach();
197-
if (window.__displaySettingsObserver) {
198-
window.__displaySettingsObserver.disconnect();
199-
window.__displaySettingsObserver = undefined;
200-
}
201-
return;
202-
}
187+
if (!btn || !panel) return;
188+
if (btn.dataset.bound === '1') return;
189+
btn.addEventListener('click', () => {
190+
panel.classList.toggle('float-panel-closed');
191+
});
192+
btn.dataset.bound = '1';
193+
}
194+
195+
function bindNavMenu() {
196+
const btn = document.getElementById('nav-menu-switch');
197+
const panel = document.getElementById('nav-menu-panel');
198+
if (!btn || !panel) return;
199+
if (btn.dataset.bound === '1') return;
200+
btn.addEventListener('click', (event) => {
201+
event.preventDefault();
202+
panel.classList.toggle('float-panel-closed');
203+
});
204+
btn.dataset.bound = '1';
203205

204-
if (!window.__displaySettingsObserver) {
205-
const observer = new MutationObserver(() => {
206-
const nextPanel = document.getElementById('display-setting');
207-
if (nextPanel) {
208-
attach();
209-
observer.disconnect();
210-
window.__displaySettingsObserver = undefined;
206+
if (!window.__navMenuOutsideHandler) {
207+
window.__navMenuOutsideHandler = (event) => {
208+
if (!panel.contains(event.target) && event.target !== btn && !btn.contains(event.target)) {
209+
panel.classList.add('float-panel-closed');
211210
}
212-
});
213-
observer.observe(document.body, { childList: true, subtree: true });
214-
window.__displaySettingsObserver = observer;
211+
};
212+
document.addEventListener('click', window.__navMenuOutsideHandler);
215213
}
216214
}
217215

@@ -240,8 +238,7 @@ function initSemifullScrollDetection() {
240238
const isHome = navbar.getAttribute('data-is-home') === 'true';
241239
const threshold = 12;
242240
const applyScrolledState = (active) => {
243-
if (active) navbar.classList.add('scrolled');
244-
else navbar.classList.remove('scrolled');
241+
if (active) navbar.classList.add('scrolled'); else navbar.classList.remove('scrolled');
245242
};
246243
if (!isHome) { applyScrolledState(true); return; }
247244

@@ -251,7 +248,12 @@ function initSemifullScrollDetection() {
251248
applyScrolledState(scrollTop > threshold);
252249
ticking = false;
253250
}
254-
function requestTick() { if (!ticking) { requestAnimationFrame(updateNavbarState); ticking = true; } }
251+
function requestTick() {
252+
if (!ticking) {
253+
requestAnimationFrame(updateNavbarState);
254+
ticking = true;
255+
}
256+
}
255257

256258
semifullScrollHandler = requestTick;
257259
window.addEventListener('scroll', requestTick, { passive: true });
@@ -261,6 +263,7 @@ function initSemifullScrollDetection() {
261263
function initNavbar() {
262264
bindDropdowns();
263265
bindDisplaySettings();
266+
bindNavMenu();
264267
initSemifullScrollDetection();
265268
}
266269

@@ -299,4 +302,4 @@ if (document.readyState === 'loading') {
299302
} else {
300303
loadPagefind();
301304
}
302-
</script>}
305+
</script>}

0 commit comments

Comments
 (0)