Vue Layout

by darkylmnx

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.1/vue-router.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.js"></script>
<div id="app"></div>

<script id="t-app" type="text/template">

	<div id="app">
    <component :is="layout">
      <router-view/>
    </component>
  </div>

</script>

<script id="default-layout" type="text/template">

	<div>
    <nav-bar />

    <div class="container section">
      <div class="columns">
        <div class="column is-8">
          <slot />
        </div>

        <div class="column is-4">
          <side-bar />
        </div>
      </div>
    </div>

    <footer-bar />
  </div>

</script>

<script id="no-sidebar-layout" type="text/template">

	<div>
    <nav-bar />

    <div class="container">
      <slot />
    </div>

    <footer-bar />
  </div>

</script>

<script id="nav-bar" type="text/template">

	<nav class="navbar is-light">
    <div class="navbar-brand">
      <div class="navbar-item" href="/">
        Vue multi layouts
      </div>

      <a class="navbar-burger" @click="open = !open">
        <span aria-hidden="true"></span>
        <span aria-hidden="true"></span>
        <span aria-hidden="true"></span>
      </a>
    </div>

    <div class="navbar-menu" :class="{'is-active': open}">
      <div class="navbar-start">
        <div class="navbar-item">
          <router-link class="button is-primary" :to="{name: 'about'}" @click.native="open = false">
            About
          </router-link>
        </div>
        <div class="navbar-item">
          <router-link class="button is-primary" to="/" @click.native="open = false">
            Posts
          </router-link>
        </div>
        <div class="navbar-item">
          <router-link class="button is-primary" :to="{name: 'photos'}" @click.native="open = false">
            Photos
          </router-link>
      ...

CSS

body {
    background: #f5f5f5;
}

.navbar {
  box-shadow: 0 2px 3px rgba(0, 0, 0, 0.2);
}

Babel + JSX

axios.defaults.baseURL = "https://jsonplaceholder.typicode.com";

const Api = {
  getPosts() {
    return axios.get("/posts");
  },

  getPost(id) {
    return axios.get("/posts/" + id);
  },

  getPhotos() {
    return axios.get("/photos");
  }
};

const default_layout = "default";

// add you loayouts to the App component
const App = {
	template: '#t-app',
  computed: {
    layout() {
      return (this.$route.meta.layout || default_layout) + "-layout";
    }
  },
  created() {
    // nothing defined here (when this.$route.path is other than "/")
    console.log(this.$route, this.$route.meta.layout);
  },
  updated() {
    // something defined here whatever the this.$route.path
    console.log(this.$route, this.$route.meta.layout);
  }
};

const NavBar = {
	template: '#nav-bar',
  data() {
    return {
      open: false
    };
  }
}

const SideBar = {
	template: '#sidebar'
}

const FooterBar = {
	template: '#footer-bar'
}

const c404 = {
	template: '#c404'
}

const About = {
	template: '#about'
}

const Home = {
	template: '#home',
  data() {
    return {
      loading: true,
      posts: null
    };
  },
  created() {
    Api.getPosts()
      .then(response => {
        this.posts = response.data;
        this.loading = false;
      })
      .catch(() => {
        alert("ERROR");
        this.loading = false;
      });
  }
};

const Photos = {
	template: '#photos',
  data() {
    return {
      loading: true,
      photos: null
    };
  },
  created() {
    Api.getPhotos()
      .then(response => {
        this.photos = response.data;
        this.loading = false;
      })
      .catch(() => {
        alert("ERROR");
        this.loading = false;
      });
  }
};

const Post = {
	template: '#post',
  data() {
    return {
      page: null,
      loading: true
    };
  },
  watch: {
    $route: {
      immediate: true,
      handler($route) {
        Api.getPost($route.params.id)
          .then(response => {
            this.page = response.data;
           ...