vue-sfc-compiler/compiler/src/core/pages-router.vue

139 lines
3.4 KiB
Vue

<template lang="pug">
.pages
.pages-list
slot(v-if="pages.error" name="error") {{ pages.error }}
slot(v-else-if="pages.data" name="list")
template(v-for="(page, id) in pages.data")
button(v-if="activePage != id" @click="showPage(id)") {{ page.name }}
p(v-else) {{ page.name }}
slot(v-else name="loader") Loading...
.active-page
div(v-if="activePage")
keep-alive
div(:is="activeComponent")
</template>
<script>
import PageLoader from './components/loader.vue'
import PageError from './components/error.vue'
export default {
name: 'pages-router',
data() {
return {
pages: {
error: null,
data: null
},
activePage: null
}
},
props: {
loader: {
type: Object,
default() {
return PageLoader
}
},
error: {
type: Object,
default() {
return PageError
}
},
prefix: {
type: String,
default: 'page-'
},
retry: {
type: Boolean,
default: false
},
source: {
required: true
},
timeout: {
type: Number,
default: 5000
},
title: {
type: String,
default: 'Router'
}
},
created() {
this.source.then(data => { // Load pages
this.pages.data = data
const loading = () => { // Show page from url or default one
this.showPage(window.location.hash.length > 0 ?
window.location.hash.substr(2) :
Object.keys(this.pages.data)[0])
}
this.$nextTick(loading)
window.onhashchange = loading
}).catch(error => {
this.pages.error = error
})
},
computed: {
activeComponent() {
return this.prefix + this.activePage
}
},
methods: {
showPage(id) {
const key = this.prefix + id
if (!(id in this.pages.data)) {
console.error(`Module not found: ${id}`)
this.$options.components[key] = this.error
return;
}
const mod = this.pages.data[id]
if (!(key in this.$options.components)) { // Must be load
this.$options.components[key] = () => ({
// Dynamicly load component
component: new Promise((resolve, reject) => {
const loaded = () => key in Vue.options.components
const load = () => loaded() ?
resolve(Vue.options.components[key]) : reject()
if (loaded() || (!this.retry && document.querySelector(`script[src="${mod.src}"]`))) { // Allready loaded
load()
return;
}
const remover = fn => e => {
if(this.retry) {
document.head.removeChild(e.target)
}
fn()
}
const el = document.createElement('script')
el.type = 'text/javascript'
el.async = true
el.src = mod.src
if (mod.integrity != null)
el.integrity = mod.integrity
el.addEventListener('load', remover(load))
el.addEventListener('error', remover(reject))
el.addEventListener('abort', remover(reject))
document.head.appendChild(el)
}),
loading: this.loader,
error: this.error,
timeout: this.timeout
})
}
document.title = `${this.title} - ${mod.name}`
window.history.pushState({}, document.title, "/#/" + id)
this.activePage = id
}
}
}
</script>