4

I want to create "skeleton loading" in Nuxt.js, but I have a problem with the moment when routing to the page. Nuxt.js doesn't change the page until the success of 'fetch' and 'asyncData' by default. Can I go to the page at once, and then wait for the data and fetch?

On the example:

<template>
    <div>
        <div class="sceleton-loading">
            <h1> <svg> <!-- h1-empty content animation--> </svg>  </h1>
        </div>
        <div class="content">
            <h1>{{ val1 }}</h1>
        </div>
    </div>
</template>
    
<script>
export default {
    async asyncData(){
        let val1 = await (new Promise(resolve => setTimeout(
            () => resolve('work'), 5000
        )));
        return {
            val1
        }
    },
}
</script>

2 Answers 2

2

The same problem I was facing, My solution is

  • First, create a middleware in /middleware directory
  • Register it in nuxt.config.js file like this
    router: {
        middleware: 'skelton'
    }

In \middleware\skelton.js

    export default function ({store}) {
      if (!process.server) {
        store.commit('ui/changeSkletonLoading', {
          skeltonLoading: true
        })
      }
    }

Add file in store\ui.js directory

    export const state = () => ({
        skeltonLoading: false,
    })

    export const mutations = {
        changeSkletonLoading(state, payload) {
           state.skeltonLoading = payload.skeltonLoading;
        }
    }

Now go to your component file and add this code

    <template>
      <div>
        <v-skeleton-loader
          class="mx-auto my-2"
          v-if="skeltonLoading"
          type="card-heading, list-item-three-line"
        ></v-skeleton-loader>
        <div v-if="!skeltonLoading">// PUT YOUR CONTENT HERE </div>
      </div>
    </template>

    <script>
    import { mapState } from "vuex";
    export default {
      computed: {
        ...mapState("ui", {
          skeltonLoading: state => state.skeltonLoading
        })
      },
      created() {
        this.$store.commit("ui/changeSkletonLoading", {
          skeltonLoading: false
        });
      }
    };
    </script>

Whenever you click to go on another route it will show you Skelton loading.

Note: It will not show Skelton loading on page load but it will show Skelton loading on page change (route navigation)

Sign up to request clarification or add additional context in comments.

Comments

0

You can create a middleware named skeleton :

export default function({ store, route }) {
  let skeleton = null;

  if (route.name.indexOf("page-one") !== -1)
    skeleton = "skeleton-page-one";
  else if (route.name.indexOf("page-two") !== -1)
    skeleton = "skeleton-page-two"; 
  ...

  store.commit("UPDATE_SKELETON", skeleton);
}

And use it in your pages :

middleware: "skeleton",

in your layout

 <v-app>
    <header/>
    <main v-if="page_loading" class="main">
      <page-one-skeleton v-if="skeleton === 'page-one'" />
      <page-two-skeleton v-if="skeleton === 'page-two'" />
    </main>
    <nuxt v-else />
    <footer/>
    <common />
  </v-app>
  <script>
  computed: {
    skeleton() {
      return this.$store.state.skeleton;
    },
    page_loading() {
      return this.$store.state.page_loading;
    }
  }
  </script>

In your store :

export const state = () => ({
  skeleton: null,
  page_loading: false

})

export const mutations = {
  UPDATE_SKELETON(state, data) {
    state.skeleton = data;
  },
  UPDATE_LOADING(state, data) {
    state.global_loading = data;
  }
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.