Изменение стилей кузова в маршрутизаторе vue
Я использую маршрутизатор Vue с двумя страницами:
let routes = [
{
path: '/',
component: require('./components/HomeView.vue')
},
{
path: '/intro',
component: require('./components/IntroView.vue')
}
]
Это прекрасно работает, за исключением того, что каждый из моих компонентов имеет разные стили кузова:
HomeView.vue:
<template>
<p>This is the home page!</p>
</template>
<script>
export default {
}
</script>
<style>
body {
background: red;
}
</style>
IntroView.vue:
<template>
<div>
<h1>Introduction</h1>
</div>
</template>
<script>
export default {
}
</script>
<style>
body {
background: pink;
}
</style>
Моя цель состоит в том, чтобы эти две страницы имели разные стили фона (в конечном итоге с переходом между ними). Но в тот момент, когда я иду на home
маршрут (с red
фоном), затем нажимаю на intro
маршрут, цвет фона остается red
(я хочу, чтобы он изменился на pink
).
Изменение: index.html:
<body>
<div id="app">
<router-link to="/" exact>Home</router-link>
<router-link to="/intro">Introduction</router-link>
<router-view></router-view>
</div>
<script src="/dist/build.js"></script>
</body>
Ответы
Ответ 1
Я работал с хуком жизненного цикла beforeCreate
и глобальной beforeCreate
стилей. В global.css
:
body.home {
background: red;
}
body.intro {
background: pink;
}
В разделе <script>
HomeView.vue
:
export default {
beforeCreate: function() {
document.body.className = 'home';
}
}
И похоже на IntroView.vue
.
Ответ 2
В качестве альтернативы вы можете использовать этот
Он позволяет управлять классами тела страницы с помощью vue-router.
Написал это, столкнувшись с подобной проблемой.
Он также ссылается на Добавить класс в тело при щелчке по компоненту?
Ответ 3
Я столкнулся с проблемой, когда захотел изменить стили тегов html
и body
вместе с контейнером #app
на определенных маршрутах, и выяснил, что по разным причинам это может быть довольно сложно.
После прочтения:
В вашем App.vue (может рассматриваться как централизованное состояние):
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'my-app',
methods: {
handleStyles () {
// Red style to the body tag for the home page
if (['/'].includes(this.$route.path)) document.body.className = 'bg-red'
// Pink style to the body tag for all other pages
else if (document.body.classList.contains('bg-red')) document.body.className = 'bg-pink'
}
},
// Handle styles when the app is initially loaded
mounted () {
this.handleStyles()
},
// Handle styles when the route changes
watch: {
'$route' () {
this.handleStyles()
}
}
}
</script>
<style>
.bg-red {
background: red;
}
.bg-pink {
background: pink;
}
</style>
Таким образом, для маршрута /
вы получаете красный стиль, а для всех остальных маршрутов применяется розовый стиль.
Логика handleStyles
могла бы обрабатываться beforeCreated
однако в моем случае это затронет только стили html
и body
но элемент #app
котором отображается представление маршрутизатора, будет доступен только после монтирования dom, так что я думаю, что это немного более расширяемое решение.
Ответ 4
watch: {
$route: {
handler (to, from) {
const body = document.getElementsByTagName('body')[0];
if (from !== undefined) {
body.classList.remove('page--' + from.name.toLowerCase());
}
body.classList.add('page--' + to.name.toLowerCase());
},
immediate: true,
}
},
Еще одно довольно простое решение, добавьте его в базовый файл App.vue. To.name может быть заменено to.meta.class или аналогичным для чего-то более конкретного. Это хорошо сделать это один раз, и это работает навсегда.
Ответ 5
Если класс является определенным видом, может быть, это поможет
methods: {
toggleBodyClass(addRemoveClass, className) {
const el = document.body;
if (addRemoveClass === 'addClass') {
el.classList.add(className);
} else {
el.classList.remove(className);
}
},
},
mounted() {
this.toggleBodyClass('addClass', 'mb-0');
},
destroyed() {
this.toggleBodyClass('removeClass', 'mb-0');
},
Переместите раздел methods
в миксин, и тогда код может быть СУХИМ.
Ответ 6
Вы также можете сделать это прямо в файле маршрутизатора, используя хук afterEach
:
mainRouter.afterEach((to) => {
if (["dialogs", "snippets"].includes(to.name)) {
document.body.style.backgroundColor = "#F7F7F7";
// or document.body.classList.add(className);
} else {
document.body.style.backgroundColor = "#FFFFFF";
// or document.body.classList.remove(className);
}
});
afterEach
документация о afterEach
to
- это объект маршрута, который содержит имя маршрута (если он назван), путь и т.д. Документация для всех реквизитов
Ответ 7
Вы можете использовать атрибут scoped в элементе style. Тогда стиль будет ограничен только этим файлом VUE.
HomeView.vue:
<template>
<p>This is the home page!</p>
</template>
<script>
export default {
}
</script>
<style scoped>
body {
background: red;
}
</style>
IntroView.vue:
<template>
<div>
<h1>Introduction</h1>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
body {
background: pink;
}
</style>