|
| 1 | +import Vue from 'vue' |
| 2 | +import { decode, parsePath, withoutBase, withoutTrailingSlash, normalizeURL } from 'ufo' |
| 3 | + |
| 4 | +import { getMatchedComponentsInstances, getChildrenComponentInstancesUsingFetch, promisify, globalHandleError, urlJoin, sanitizeComponent } from './utils' |
| 5 | +import NuxtError from './components/nuxt-error.vue' |
| 6 | +import NuxtLoading from './components/nuxt-loading.vue' |
| 7 | +import NuxtBuildIndicator from './components/nuxt-build-indicator' |
| 8 | + |
| 9 | +import _6f6c098b from '..\\layouts\\default.vue' |
| 10 | + |
| 11 | +const layouts = { "_default": sanitizeComponent(_6f6c098b) } |
| 12 | + |
| 13 | +export default { |
| 14 | + render (h, props) { |
| 15 | + const loadingEl = h('NuxtLoading', { ref: 'loading' }) |
| 16 | + |
| 17 | + const layoutEl = h(this.layout || 'nuxt') |
| 18 | + const templateEl = h('div', { |
| 19 | + domProps: { |
| 20 | + id: '__layout' |
| 21 | + }, |
| 22 | + key: this.layoutName |
| 23 | + }, [layoutEl]) |
| 24 | + |
| 25 | + const transitionEl = h('transition', { |
| 26 | + props: { |
| 27 | + name: 'layout', |
| 28 | + mode: 'out-in' |
| 29 | + }, |
| 30 | + on: { |
| 31 | + beforeEnter (el) { |
| 32 | + // Ensure to trigger scroll event after calling scrollBehavior |
| 33 | + window.$nuxt.$nextTick(() => { |
| 34 | + window.$nuxt.$emit('triggerScroll') |
| 35 | + }) |
| 36 | + } |
| 37 | + } |
| 38 | + }, [templateEl]) |
| 39 | + |
| 40 | + return h('div', { |
| 41 | + domProps: { |
| 42 | + id: '__nuxt' |
| 43 | + } |
| 44 | + }, [ |
| 45 | + loadingEl, |
| 46 | + h(NuxtBuildIndicator), |
| 47 | + transitionEl |
| 48 | + ]) |
| 49 | + }, |
| 50 | + |
| 51 | + data: () => ({ |
| 52 | + isOnline: true, |
| 53 | + |
| 54 | + layout: null, |
| 55 | + layoutName: '', |
| 56 | + |
| 57 | + nbFetching: 0 |
| 58 | + }), |
| 59 | + |
| 60 | + beforeCreate () { |
| 61 | + Vue.util.defineReactive(this, 'nuxt', this.$options.nuxt) |
| 62 | + }, |
| 63 | + created () { |
| 64 | + // Add this.$nuxt in child instances |
| 65 | + this.$root.$options.$nuxt = this |
| 66 | + |
| 67 | + if (process.client) { |
| 68 | + // add to window so we can listen when ready |
| 69 | + window.$nuxt = this |
| 70 | + |
| 71 | + this.refreshOnlineStatus() |
| 72 | + // Setup the listeners |
| 73 | + window.addEventListener('online', this.refreshOnlineStatus) |
| 74 | + window.addEventListener('offline', this.refreshOnlineStatus) |
| 75 | + } |
| 76 | + // Add $nuxt.error() |
| 77 | + this.error = this.nuxt.error |
| 78 | + // Add $nuxt.context |
| 79 | + this.context = this.$options.context |
| 80 | + }, |
| 81 | + |
| 82 | + async mounted () { |
| 83 | + this.$loading = this.$refs.loading |
| 84 | + }, |
| 85 | + |
| 86 | + watch: { |
| 87 | + 'nuxt.err': 'errorChanged' |
| 88 | + }, |
| 89 | + |
| 90 | + computed: { |
| 91 | + isOffline () { |
| 92 | + return !this.isOnline |
| 93 | + }, |
| 94 | + |
| 95 | + isFetching () { |
| 96 | + return this.nbFetching > 0 |
| 97 | + }, |
| 98 | + }, |
| 99 | + |
| 100 | + methods: { |
| 101 | + refreshOnlineStatus () { |
| 102 | + if (process.client) { |
| 103 | + if (typeof window.navigator.onLine === 'undefined') { |
| 104 | + // If the browser doesn't support connection status reports |
| 105 | + // assume that we are online because most apps' only react |
| 106 | + // when they now that the connection has been interrupted |
| 107 | + this.isOnline = true |
| 108 | + } else { |
| 109 | + this.isOnline = window.navigator.onLine |
| 110 | + } |
| 111 | + } |
| 112 | + }, |
| 113 | + |
| 114 | + async refresh () { |
| 115 | + const pages = getMatchedComponentsInstances(this.$route) |
| 116 | + |
| 117 | + if (!pages.length) { |
| 118 | + return |
| 119 | + } |
| 120 | + this.$loading.start() |
| 121 | + |
| 122 | + const promises = pages.map(async (page) => { |
| 123 | + let p = [] |
| 124 | + |
| 125 | + // Old fetch |
| 126 | + if (page.$options.fetch && page.$options.fetch.length) { |
| 127 | + p.push(promisify(page.$options.fetch, this.context)) |
| 128 | + } |
| 129 | + |
| 130 | + if (page.$options.asyncData) { |
| 131 | + p.push( |
| 132 | + promisify(page.$options.asyncData, this.context) |
| 133 | + .then((newData) => { |
| 134 | + for (const key in newData) { |
| 135 | + Vue.set(page.$data, key, newData[key]) |
| 136 | + } |
| 137 | + }) |
| 138 | + ) |
| 139 | + } |
| 140 | + |
| 141 | + // Wait for asyncData & old fetch to finish |
| 142 | + await Promise.all(p) |
| 143 | + // Cleanup refs |
| 144 | + p = [] |
| 145 | + |
| 146 | + if (page.$fetch) { |
| 147 | + p.push(page.$fetch()) |
| 148 | + } |
| 149 | + // Get all component instance to call $fetch |
| 150 | + for (const component of getChildrenComponentInstancesUsingFetch(page.$vnode.componentInstance)) { |
| 151 | + p.push(component.$fetch()) |
| 152 | + } |
| 153 | + |
| 154 | + return Promise.all(p) |
| 155 | + }) |
| 156 | + try { |
| 157 | + await Promise.all(promises) |
| 158 | + } catch (error) { |
| 159 | + this.$loading.fail(error) |
| 160 | + globalHandleError(error) |
| 161 | + this.error(error) |
| 162 | + } |
| 163 | + this.$loading.finish() |
| 164 | + }, |
| 165 | + errorChanged () { |
| 166 | + if (this.nuxt.err) { |
| 167 | + if (this.$loading) { |
| 168 | + if (this.$loading.fail) { |
| 169 | + this.$loading.fail(this.nuxt.err) |
| 170 | + } |
| 171 | + if (this.$loading.finish) { |
| 172 | + this.$loading.finish() |
| 173 | + } |
| 174 | + } |
| 175 | + |
| 176 | + let errorLayout = (NuxtError.options || NuxtError).layout; |
| 177 | + |
| 178 | + if (typeof errorLayout === 'function') { |
| 179 | + errorLayout = errorLayout(this.context) |
| 180 | + } |
| 181 | + |
| 182 | + this.nuxt.errPageReady = true |
| 183 | + this.setLayout(errorLayout) |
| 184 | + } |
| 185 | + }, |
| 186 | + |
| 187 | + setLayout (layout) { |
| 188 | + if(layout && typeof layout !== 'string') { |
| 189 | + throw new Error('[nuxt] Avoid using non-string value as layout property.') |
| 190 | + } |
| 191 | + |
| 192 | + if (!layout || !layouts['_' + layout]) { |
| 193 | + layout = 'default' |
| 194 | + } |
| 195 | + this.layoutName = layout |
| 196 | + this.layout = layouts['_' + layout] |
| 197 | + return this.layout |
| 198 | + }, |
| 199 | + loadLayout (layout) { |
| 200 | + if (!layout || !layouts['_' + layout]) { |
| 201 | + layout = 'default' |
| 202 | + } |
| 203 | + return Promise.resolve(layouts['_' + layout]) |
| 204 | + }, |
| 205 | + }, |
| 206 | + |
| 207 | + components: { |
| 208 | + NuxtLoading |
| 209 | + } |
| 210 | +} |
0 commit comments