@daniel_wesson

NuxtJS 3: Как сделать чтобы страницы могли изменять глобальное состояние приложения?

Использую nuxt 3 + pinia, упрощенный пример того чего хотелось бы: на сайте имеется шапка, подключенная в layouts/default.vue, все отлично - она отображается на каждой странице.

Обобщенно можно сформулировать следующую задачу - на главной странице шапка должна быть absolute (чтобы под ней был виден приветственный баннер), на других страницах, она должна быть relative.

Создал pinia-хранилище useHeaderStore в котором есть свойство isAbsolute и метод setAbsolute. Каждая страница может дернуть setAbsolute, который изменит состояние absolute и к шапке применяется соответствующее css-свойство. В целом это работает, НО: nuxt на сервере сначала рендерит шапку, потом страницу, которая должно меняет состояние шапки. Получается что пользователь получает html c шапкой, имеющей начальное значение absolute, а не то, которое установила страница в ходе рендеринга на сервере.

Как страница может настроить общее состояние приложения и чтоб все работало, даже если выключить JS в браузере? Накидайте идей, буду благодарен)

export const useHeaderStore = defineStore('header', () => {
	const isAbsolute = ref(false)
	const setAbsolute = (value: boolean) => isAbsolute.value = value

	return { isAbsolute, setAbsolute }
})


<template>
	<header :class="{ 'is-absolute': isAbsolute }"></header>
</template>

<script setup lang="ts">

import { useHeaderStore } from '~/stores/header'

const store = useHeaderStore()
const isAbsolute = store.isAbsolute

</script>


<template>
	<h1>Главная страница</h1>
</template>

<script setup lang="ts">

import { useHeaderStore } from '~/stores/header'

const { setAbsolute } = useHeaderStore()
setAbsolute(true)

</script>
  • Вопрос задан
  • 974 просмотра
Решения вопроса 1
@daniel_wesson Автор вопроса
Решение оказалось довольно простым: использовать definePageMeta
В нем можно определить произвольную конфигурацию которая нужна странице. Или, как в моем случае, достаточно обернуть setAbsolute в middleware:
<script setup lang="ts">

import { definePageMeta } from '#imports'
import { useHeaderStore } from '~/stores/header'

definePageMeta({
	middleware: [() => {
		const { setAbsolute } = useHeaderStore()
		setAbsolute(false)
	}]
})

</script>
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
neuotq
@neuotq
Прокрастинация
Вы немного перемудрили, стор в данном случае вам не нужен, даже логически зачем. Ведь это не доп инфа от пользователя, какое-то дополнительное состояние приложение которое нужно отслеживать и тд и тп.
У вас уже есть роутер, который управляет и держит в себе необходимое состояние и удобный доступ к текущему пути через useRoute или $route внутри vue компонента.
Вот документация и на Vue
https://router.vuejs.org/api/interfaces/routelocat...
https://router.vuejs.org/api/interfaces/router.html.
// Получим объект текщего пути
const { currentRoute } = useRouter();
/*
Далее у него можно брать уже name, path и тп
*/

<template>
  <header :class="{ 'is-absolute': isAbsolute }"></header>
</template>

<script setup lang="ts">
const { currentRoute } = useRouter();
/* Заменить на своё */
const isAbsolute = currentRoute.name === 'index' ;
</script>


PS отдельный вопрос что в целом движ по вёрстке возможно спорный, что ради баннера нужно менять такие штуки у ключевых элементов, возможно логику нужно поменять, а может всё ок, но это уже другая история.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы