App.js 5.0 KB

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