nuxt.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import Vue from 'vue'
  2. import { compile } from '../utils'
  3. <% if (components.ErrorPage) { %>
  4. <% if (('~@').includes(components.ErrorPage.charAt(0))) { %>
  5. import NuxtError from '<%= components.ErrorPage %>'
  6. <% } else { %>
  7. import NuxtError from '<%= "../" + components.ErrorPage %>'
  8. <% } %>
  9. <% } else { %>
  10. import NuxtError from './nuxt-error.vue'
  11. <% } /* components */ %>
  12. import NuxtChild from './nuxt-child'
  13. <%= isTest ? '// @vue/component' : '' %>
  14. export default {
  15. name: 'Nuxt',
  16. components: {
  17. NuxtChild,
  18. NuxtError
  19. },
  20. props: {
  21. nuxtChildKey: {
  22. type: String,
  23. default: undefined
  24. },
  25. keepAlive: Boolean,
  26. keepAliveProps: {
  27. type: Object,
  28. default: undefined
  29. },
  30. name: {
  31. type: String,
  32. default: 'default'
  33. }
  34. },
  35. errorCaptured (error) {
  36. // if we receive and error while showing the NuxtError component
  37. // capture the error and force an immediate update so we re-render
  38. // without the NuxtError component
  39. if (this.displayingNuxtError) {
  40. this.errorFromNuxtError = error
  41. this.$forceUpdate()
  42. }
  43. },
  44. computed: {
  45. routerViewKey () {
  46. // If nuxtChildKey prop is given or current route has children
  47. if (typeof this.nuxtChildKey !== 'undefined' || this.$route.matched.length > 1) {
  48. return this.nuxtChildKey || compile(this.$route.matched[0].path)(this.$route.params)
  49. }
  50. const [matchedRoute] = this.$route.matched
  51. if (!matchedRoute) {
  52. return this.$route.path
  53. }
  54. const Component = matchedRoute.components.default
  55. if (Component && Component.options) {
  56. const { options } = Component
  57. if (options.key) {
  58. return (typeof options.key === 'function' ? options.key(this.$route) : options.key)
  59. }
  60. }
  61. const strict = /\/$/.test(matchedRoute.path)
  62. return strict ? this.$route.path : this.$route.path.replace(/\/$/, '')
  63. }
  64. },
  65. beforeCreate () {
  66. Vue.util.defineReactive(this, 'nuxt', this.$root.$options.nuxt)
  67. },
  68. render (h) {
  69. // if there is no error
  70. if (!this.nuxt.err) {
  71. // Directly return nuxt child
  72. return h('NuxtChild', {
  73. key: this.routerViewKey,
  74. props: this.$props
  75. })
  76. }
  77. // if an error occurred within NuxtError show a simple
  78. // error message instead to prevent looping
  79. if (this.errorFromNuxtError) {
  80. this.$nextTick(() => (this.errorFromNuxtError = false))
  81. return h('div', {}, [
  82. h('h2', 'An error occurred while showing the error page'),
  83. h('p', 'Unfortunately an error occurred and while showing the error page another error occurred'),
  84. h('p', `Error details: ${this.errorFromNuxtError.toString()}`),
  85. h('nuxt-link', { props: { to: '/' } }, 'Go back to home')
  86. ])
  87. }
  88. // track if we are showing the NuxtError component
  89. this.displayingNuxtError = true
  90. this.$nextTick(() => (this.displayingNuxtError = false))
  91. return h(NuxtError, {
  92. props: {
  93. error: this.nuxt.err
  94. }
  95. })
  96. }
  97. }