[VueJS, Разработка веб-сайтов] Переключение шаблона страниц во vuejs

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
04-Авг-2020 16:30

Иногда в приложении требуется шаблоны для различных страниц, чтобы не копировать код от компонента к компоненту, мы прописываем шаблон в основном компоненте (он же, обычно, App.vue) и с помощью <router-view> подставляем в него различные вьюшки.

Как мы видим, у различных страниц общая шапка. Сайт.
А что, если нам необходимо сделать несколько шаблонов для разных страниц или состояний приложения? Этим мы сейчас и займемся.
Первым делом нам необходимо Vue Js приложение с подключенным роутером.
Что из себя представляют шаблоны? Правильно, обычные компоненты, которые будут вызываться в зависимости от того или иного условия, будь то активная странница, статус аутентификации или (по бреду) время суток.
Подготовим основной компонент для работы с шаблонами.
Если вы создавали проект через Vue-Cli у вас он выглядит примерно так:
//ВАШ_ПРОЕКТ/src/App.vue
<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </div>
    <router-view/>
  </div>
</template>
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
#nav {
  padding: 30px;
}
#nav a {
  font-weight: bold;
  color: #2c3e50;
}
#nav a.router-link-exact-active {
  color: #42b983;
}
</style>
Нам необходимо добавить новое вычисляемое свойство (Computed) в секцию «script» (если у вас ее нет, скопируйте ее из любого vue компонента).
Это свойство будет возвращать нам имя компонента-шаблона в зависимости от того или иного условия, в данном примере — шаблон будет привязан к странице.
//ВАШ_ПРОЕКТ/src/App.vue
...
<script>
    export default {
        computed: {
            //Это самое вычисляемое свойство
            layout(){
                //Вернем имя шаблона из роута или дефолтное значение
                  //(шаблон для страниц, для которых мы не указали шаблон)
                return this.$route.meta.layout || "default-layout"
            }
        }
    }
</script>
...

Отредактируем секцию «template» — добавим в нее динамический компонент, который будет меняться в зависимости от значения layout.
//ВАШ_ПРОЕКТ/src/App.vue
<template>
  <div id="app">
      <!--Динамический компонент-->
      <component :is="layout">
          <router-view/>
      </component>
  </div>
</template>
...

Теперь создадим пару шаблонов.
Для удобства будем хранить их в отдельной папке «layouts».

По значимости папка не сильно ушла от components или view, просто удобно.
Есть у Vue такой элемент — «slot», который позволит нам подставлять наши представления в компонент-шаблон. При отрисовке он заменяется на контент, который мы укажем при вызове компонента. Создадим три шаблона, пусть они будут одинаковыми, с разницей в цвете шапки и подвала, для наглядности.
Синий шаблон, дефолтный:
//ВАШ_ПРОЕКТ/src/layouts/Default.vue
<template>
    <div>
        <header>
            <ul class="nav">
                <li><router-link class="link" to="/">Домашняя страница</router-link></li>
                <li><router-link class="link" to="/page2">Страница 1</router-link></li>
                <li><router-link class="link" to="/page3">Страница 2</router-link></li>
                <li><router-link class="link" to="/page4">Страница 2</router-link></li>
            </ul>
        </header>
        <section class="content">
            <!--Элемент, который при отрисовке будет заменен на ваш view-->
            <slot/>
        </section>
        <footer>
        </footer>
    </div>
</template>
<script>
    export default {
        name: "Default"
    }
</script>
<style scoped>
    header{
        background-color: blue;
        height: 70px;
        display: flex;
        align-items: center;
    }
    footer{
        background-color: blue;
        height: 70px;
    }
    .content{
        min-height: calc(100vh - 140px);
    }
    ul{
        list-style: none;
        margin: 0;
        color: white;
    }
    li{
        color: white;
        display: inline;
        margin: 0 5px;
    }
    .link{
        color: white;
        text-decoration: none;
    }
</style>

Зеленый шаблон:
//ВАШ_ПРОЕКТ/src/layouts/Green.vue
<template>
    <div>
        <header>
            <ul class="nav">
                <li><router-link class="link" to="/">Домашняя страница</router-link></li>
                <li><router-link class="link" to="/page2">Страница 1</router-link></li>
                <li><router-link class="link" to="/page3">Страница 2</router-link></li>
                <li><router-link class="link" to="/page4">Страница 2</router-link></li>
            </ul>
        </header>
        <section class="content">
            <!--Элемент, который при отрисовке будет заменен на ваш view-->
            <slot/>
        </section>
        <footer>
        </footer>
    </div>
</template>
<script>
    export default {
        name: "green"
    }
</script>
<style scoped>
    header{
        background-color: green;
        height: 70px;
        display: flex;
        align-items: center;
    }
    footer{
        background-color: green;
        height: 70px;
    }
    .content{
        min-height: calc(100vh - 140px);
    }
    ul{
        list-style: none;
        margin: 0;
        color: white;
    }
    li{
        color: white;
        display: inline;
        margin: 0 5px;
    }
    .link{
        color: white;
        text-decoration: none;
    }
</style>

Красный шаблон:
//ВАШ_ПРОЕКТ/src/layouts/Red.vue
<template>
    <div>
        <header>
            <ul class="nav">
                <li><router-link class="link" to="/">Домашняя страница</router-link></li>
                <li><router-link class="link" to="/page2">Страница 1</router-link></li>
                <li><router-link class="link" to="/page3">Страница 2</router-link></li>
                <li><router-link class="link" to="/page4">Страница 2</router-link></li>
            </ul>
        </header>
        <section class="content">
            <!--Элемент, который при отрисовке будет заменен на ваш view-->
            <slot/>
        </section>
        <footer>
        </footer>
    </div>
</template>
<script>
    export default {
        name: "Red"
    }
</script>
<style scoped>
    header{
        background-color: red;
        height: 70px;
        display: flex;
        align-items: center;
    }
    footer{
        background-color: red;
        height: 70px;
    }
    .content{
        min-height: calc(100vh - 140px);
    }
    ul{
        list-style: none;
        margin: 0;
        color: white;
    }
    li{
        color: white;
        display: inline;
        margin: 0 5px;
    }
    .link{
        color: white;
        text-decoration: none;
    }
</style>

Теперь зарегистрируем эти компоненты-шаблоны в нашем Vue.
//ВАШ_ПРОЕКТ/src/main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
//Подключим файлы компонентов
import DefaultLayout from "./layouts/Default"
import GreenLayout from "./layouts/Green"
import RedLayout from "./layouts/Red"
//И зарегистрируем их в нашем приложении
Vue.component("default-layout", DefaultLayout)
Vue.component("green-layout", GreenLayout)
Vue.component("red-layout", RedLayout)
Vue.config.productionTip = false
new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

Отлично! Шаблоны готовы, давайте создадим четыре представления(страницы), два из которых будут отрисовываться с синим шаблоном, а два остальных с красным и зеленым. Они тоже будут одинаковыми, только с разными заголовками.
//ВАШ_ПРОЕКТ/src/views/page1.vue
<template>
    <div>
        <h1>Синий шаблон</h1>
    </div>
</template>
<script>
    export default {
        name: "Page1"
    }
</script>
<style scoped>

</style>
//ВАШ_ПРОЕКТ/src/views/page2.vue
<template>
    <div>
        <h1>Зеленый шаблон</h1>
    </div>
</template>
<script>
    export default {
        name: "Page2"
    }
</script>
<style scoped>
</style>

//ВАШ_ПРОЕКТ/src/views/page3.vue
<template>
    <div>
        <h1>Красный шаблон</h1>
    </div>
</template>
<script>
    export default {
        name: "Page3"
    }
</script>
<style scoped>
</style>

//ВАШ_ПРОЕКТ/src/views/page4.vue
<template>
    <div>
        <h1>Еще один синий шаблон</h1>
    </div>
</template>
<script>
    export default {
        name: "Page4"
    }
</script>
<style scoped>
</style>

Теперь добавим роуты под наши страницы, и в мета-данных укажем какой шаблон им использовать при отрисовке.
import Vue from 'vue'
import VueRouter from 'vue-router'
//Подключим наши страницы
import Page1 from "../views/Page1"
import Page2 from "../views/Page2"
import Page3 from "../views/Page3"
import Page4 from "../views/Page4"
Vue.use(VueRouter)
const routes = [
    {
        path: '/',
        name: 'Home',
        component: Page1
        //Так, как синий шаблон у нас является дефолтным, его можно не указывать в мета-данных
    },
    {
        path: '/page2',
        name: 'Page2',
        component: Page2,
        //А вот это свойство как раз будет содержать название компонента-шаблона,
        //который мы хотим использовать для данной страницы
        meta:{
            layout: "green-layout"
        }
    },
    {
        path: '/page3',
        name: 'Page3',
        component: Page3,
        meta:{
            layout: "red-layout"
        }
    },
    {
        path: '/page4',
        name: 'Page4',
        component: Page4,
        //И снова ничего не указываем, чтобы задействовать дефолтный шаблон
    }
]
const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes
})
export default router

Запускаем наше приложение и проверяем:

Целиком код можно посмотреть тут
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_vuejs, #_razrabotka_vebsajtov (Разработка веб-сайтов), #_vue.js, #_javascript, #_vuejs, #_razrabotka_vebsajtov (
Разработка веб-сайтов
)
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 23-Ноя 00:29
Часовой пояс: UTC + 5