123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- import Vue from 'vue'
- import { hasFetch, normalizeError, addLifecycleHook, createGetCounter } from '../utils'
- const isSsrHydration = (vm) => vm.$vnode && vm.$vnode.elm && vm.$vnode.elm.dataset && vm.$vnode.elm.dataset.fetchKey
- const nuxtState = window.<%= globals.context %>
- export default {
- beforeCreate () {
- if (!hasFetch(this)) {
- return
- }
- this._fetchDelay = typeof this.$options.fetchDelay === 'number' ? this.$options.fetchDelay : 200
- Vue.util.defineReactive(this, '$fetchState', {
- pending: false,
- error: null,
- timestamp: Date.now()
- })
- this.$fetch = $fetch.bind(this)
- addLifecycleHook(this, 'created', created)
- addLifecycleHook(this, 'beforeMount', beforeMount)
- }
- }
- function beforeMount() {
- if (!this._hydrated) {
- return this.$fetch()
- }
- }
- function created() {
- if (!isSsrHydration(this)) {
- <% if (isFullStatic) { %>createdFullStatic.call(this)<% } %>
- return
- }
- // Hydrate component
- this._hydrated = true
- this._fetchKey = this.$vnode.elm.dataset.fetchKey
- const data = nuxtState.fetch[this._fetchKey]
- // If fetch error
- if (data && data._error) {
- this.$fetchState.error = data._error
- return
- }
- // Merge data
- for (const key in data) {
- Vue.set(this.$data, key, data[key])
- }
- }
- <% if (isFullStatic) { %>
- function createdFullStatic() {
- // Check if component has been fetched on server
- let fetchedOnServer = this.$options.fetchOnServer !== false
- if (typeof this.$options.fetchOnServer === 'function') {
- fetchedOnServer = this.$options.fetchOnServer.call(this) !== false
- }
- if (!fetchedOnServer || this.<%= globals.nuxt %>.isPreview || !this.<%= globals.nuxt %>._pagePayload) {
- return
- }
- this._hydrated = true
- const defaultKey = this.$options._scopeId || this.$options.name || ''
- const getCounter = createGetCounter(this.<%= globals.nuxt %>._fetchCounters, defaultKey)
- if (typeof this.$options.fetchKey === 'function') {
- this._fetchKey = this.$options.fetchKey.call(this, getCounter)
- } else {
- const key = 'string' === typeof this.$options.fetchKey ? this.$options.fetchKey : defaultKey
- this._fetchKey = key ? key + ':' + getCounter(key) : String(getCounter(key))
- }
- const data = this.<%= globals.nuxt %>._pagePayload.fetch[this._fetchKey]
- // If fetch error
- if (data && data._error) {
- this.$fetchState.error = data._error
- return
- }
- // If there is a missing payload
- if (!data) {
- this.$fetch()
- return
- }
- // Merge data
- for (const key in data) {
- Vue.set(this.$data, key, data[key])
- }
- }
- <% } %>
- function $fetch() {
- if (!this._fetchPromise) {
- this._fetchPromise = $_fetch.call(this)
- .then(() => { delete this._fetchPromise })
- }
- return this._fetchPromise
- }
- async function $_fetch() {
- this.<%= globals.nuxt %>.nbFetching++
- this.$fetchState.pending = true
- this.$fetchState.error = null
- this._hydrated = false
- let error = null
- const startTime = Date.now()
- try {
- await this.$options.fetch.call(this)
- } catch (err) {
- if (process.dev) {
- console.error('Error in fetch():', err)
- }
- error = normalizeError(err)
- }
- const delayLeft = this._fetchDelay - (Date.now() - startTime)
- if (delayLeft > 0) {
- await new Promise(resolve => setTimeout(resolve, delayLeft))
- }
- this.$fetchState.error = error
- this.$fetchState.pending = false
- this.$fetchState.timestamp = Date.now()
- this.$nextTick(() => this.<%= globals.nuxt %>.nbFetching--)
- }
|