在 Symfony 7 中使用 AssetMapper 在页面加载时执行 JavaScript 在点击链接后失败

问题描述 投票:0回答:1

我正在尝试在

BootStrap
中实现
Symfony
的颜色切换器。

我使用

BootStrap
添加了
AssetMapper
,一切正常。

然后,我将颜色切换器从

BootStrap
的示例页面复制到
twig
模板中,以及它的
CSS
JS
代码(如
assets
)。

我有一个

Controller
路由到
/
,其模板包括颜色切换器模板。

当我在浏览器中打开页面时,一切似乎都正常工作,但是,如果我在该页面中添加链接(指向其自身或其他页面),则无关紧要 - 颜色切换器将无法在新页面中工作,除非我按

F5
或以其他方式重新加载页面。

我发现初始化颜色切换器的

JavaScript
代码在初始页面加载或重新加载时运行,但是当通过单击链接更改页面时,它不会在目标页面上再次执行。

我尝试添加类似的内容:

if (document.readyState !== 'loading') {
    console.log('document is already ready, just execute code here');
    initThemeSwitcher();
} else {
    document.addEventListener('DOMContentLoaded', function () {
        console.log('document was not ready, place code here');
        initThemeSwitcher();
    });
}

再次,控制台只有在初始页面加载或强制重新加载时才会运行此代码。

所以我的问题是:为什么此代码仅在从服务器获取文件时运行,而不是通过单击链接移动到不同页面(或同一页面)时运行?

编辑刚刚注意到

Stimulus Controllers
发生了同样的事情:它们在页面加载时工作,但当我点击链接时,它们停止工作,直到我重新加载页面(例如键盘上的
F5

symfony bootstrap-5 symfony-assetmapper
1个回答
0
投票

我仍然不确定为什么将

EventListener
添加到
DOMContentLoaded
只适用于加载的第一页,但我设法找到了解决方法。

我没有使用

bootstrap
网站上的“原样”代码,而是用它制作了
Stimulus Controller
- 对代码进行了一些更改,这样就不会使用
DOMContentLoaded

我最终得到以下

Stimulus Controller

import { Controller } from '@hotwired/stimulus';

export default class extends Controller {
    'use strict'
    connect() {
        const getStoredTheme = () => localStorage.getItem('theme')
        const setStoredTheme = theme => localStorage.setItem('theme', theme)

        const getPreferredTheme = () => {
            const storedTheme = getStoredTheme()
                if (storedTheme) {
                    return storedTheme
                }

                return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
        }

        const setTheme = theme => {
            if (theme === 'auto') {
                document.documentElement.setAttribute('data-bs-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'))
            } else {
                document.documentElement.setAttribute('data-bs-theme', theme)
            }
        }

        setTheme(getPreferredTheme())

        const showActiveTheme = (theme, focus = false) => {
            const themeSwitcher = document.querySelector('#bd-theme')

            if (!themeSwitcher) {
                return
            }

            const themeSwitcherText = document.querySelector('#bd-theme-text')
            const activeThemeIcon = document.querySelector('.theme-icon-active use')
            const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`)
            const svgOfActiveBtn = btnToActive.querySelector('svg use').getAttribute('href')

            document.querySelectorAll('[data-bs-theme-value]').forEach(element => {
                element.classList.remove('active')
                element.setAttribute('aria-pressed', 'false')
            })

            btnToActive.classList.add('active')
            btnToActive.setAttribute('aria-pressed', 'true')
            activeThemeIcon.setAttribute('href', svgOfActiveBtn)
            const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`
            themeSwitcher.setAttribute('aria-label', themeSwitcherLabel)

            if (focus) {
                themeSwitcher.focus()
            }
        }

        window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
            const storedTheme = getStoredTheme()
            if (storedTheme !== 'light' && storedTheme !== 'dark') {
                setTheme(getPreferredTheme())
            }
        })

        document.querySelectorAll('[data-bs-theme-value]').forEach(toggle => {
            toggle.addEventListener('click', () => {
                const theme = toggle.getAttribute('data-bs-theme-value')
                setStoredTheme(theme)
                setTheme(theme)
                showActiveTheme(theme, true)
            })
        })
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.