const Home = { template: '<main-layout><p>home page</p></main-layout>' }
const About = { template: '<main-layout><p>about page</p></main-layout>' }
const NotFound = { template: '<main-layout><p>Page not found</p></main-layout>' }
const routes = {
'/': Home,
'/about': About
}
Vue.component('v-link', {
template: `
<a
v-bind:href="href"
v-bind:class="{ active: isActive }"
v-on:click="go">
<slot></slot>
</a>
`,
props: {
href: {
type:String,
required: true
}
},
computed: {
isActive () {
return this.href === this.$root.currentRoute
}
},
methods: {
go (event) {
event.preventDefault()
this.$root.currentRoute = this.href
window.history.pushState(
null,
routes[this.href],
this.href
)
}
}
})
Vue.component('main-layout', {
template: `
<div>
<v-link href="/">Home</v-link>
<v-link href="/about">About</v-link>
<slot></slot>
</div>
`
})
new Vue({
el: '#app',
data: {
currentRoute: window.location.pathname
},
computed: {
ViewComponent () {
return routes[this.currentRoute] || NotFound
}
},
render (h) { return h(this.ViewComponent) }
})
window.addEventListener('popstate', () => {
app.currentRoute = window.location.pathname
})
<div id="app"></div>
.active {
color: cornflowerblue;
}
External resources loaded into this fiddle: