Switching page template in vuejs

Sometimes an application requires templates for different pages, so as not to copy the code from component to component, we write the template in the main component (aka App.vue, usually) and use <router-view> to substitute various views into it.



image


As we can see, different pages have a common header. Website.



What if we need to make several templates for different pages or application states? This is what we will do now.



First of all we need a Vue Js application with a connected router.



? , , , , ( ) .



.



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>

...


Now let's create a couple of templates.



For convenience, we will store them in a separate "layouts" folder.



screenshot of folder structure


In terms of importance, the folder has not gone far from components or view, it's just convenient.



Vue has a slot element that will allow us to inject our views into a template component. When rendered, it is replaced with content that we will specify when calling the component. Let's create three templates, let them be the same, with a difference in the color of the header and footer, for clarity.



Blue template, default:





//_/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>


Green pattern:



//_/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>


Red pattern:



//_/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>


Let's now register these template components in our 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')


Excellent! The templates are ready, let's create four views (pages), two of which will be rendered with a blue template, and the other two with a red and green one. They will also be the same, only with different titles.



//_/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>


Now we will add routes for our pages, and in the metadata we will indicate which template to use for rendering.



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


We launch our application and check: The



image



whole code can be viewed here




All Articles