@gracer

Как сделать загрузочный экран на Vue?

Приветствую.
Делаю тестовый проект на пощупать vue. Есть такие этапы:
1) Загружается html страница с #app элементом
2) Грузятся скрипты с defer
3) В скриптах маунтится рутовый компонент, роутер и т.п.
4) Первый компонент-страница выполняет подключение к серверу
5) Сервер докладывает о готовности соединения
6) Приложение готово к работе
Хочу сделать загрузочный экран, лоадер, или как это назвать слой на весь экран и по середине гифка, который будет показываться на этапах общения с сервером. И есть у меня 2 вопроса. Каким способом такое лучше реализовать во вью-приложении? И как сделать чтобы
этот экран показывался сразу после этапа 1 без ожидания загрузки всех vue компонентов?
  • Вопрос задан
  • 1130 просмотров
Решения вопроса 2
delphinpro
@delphinpro
frontend developer
<div id="app">
</div>


#app[v-cloak] {
  width: 100%;
  height: 100vh;
  background: url('loader.gif') no-repeat center;
}

CSS разместить прямо в странице, в секции head
Ответ написан
nuykon
@nuykon
Full Stack Developer
Примерно так,

Первый способ - vuex

index.html:
<div class="preloader"></div>
  <style>.preloader{/* preloader styles */}</style>
  <div id="app"></div>


App.vue:
<template>
  <div>
    <router-view />
  </div>
</template>

<script>
import { mapState } from 'vuex';

const preloader = document.querySelector('.preloader');

export default {
  computed: {
    ...mapState('app', ['loading']),
  },
  watch: {
    loading: {
      handler(val) {
        preloader.style.display = val ? '' : 'none';
      },
      immediate: true,
    },
  },
};
</script>


store/modules/app.js:
import Vue from 'vue';

export const state = {
  loading: true,
};

export const mutations = {
  SET_LOADING(state, loading) {
    state.loading = loading;
  },
};

export const actions = {
  setLoading({ commit }, loading) {
    commit('SET_LOADING', loading);
  },
};


YouPage.vue:
<script>
import axios from 'axios';
import { mapActions } from 'vuex';

export default {
  methods: {
    ...mapActions('app', ['setLoading']),
  },
  created() {
    axios.get('/api/page-data').then(res => {
      console.dir(res);
    }).catch(err => {
      console.dir(err);
    }).finally(() => this.setLoading(false));
  }
};
</script>


Если vuex не используете или нет нужды, можно обойтись событиями:

index.html:
<div class="preloader"></div>
  <style>.preloader{/* preloader styles */}</style>
  <div id="app"></div>


App.vue:
<template>
  <div>
    <router-view />
  </div>
</template>

<script>
const preloader = document.querySelector('.preloader');

export default {
  data() {
    return {
      loading: true,
    };
  },
  methods: {
    setLoading(loading) {
      this.loading = loading;
      preloader.style.display = loading ? '' : 'none';
    },
  },
  mounted() {
    this.$on('set-loading', this.setLoading);
  },
  destroyed() {
    this.$off('set-loading', this.setLoading);
  }
};
</script>


YouPage.vue:
<script>
import axios from 'axios';

export default {
  created() {
    axios.get('/api/page-data').then(res => {
      console.dir(res);
    }).catch(err => {
      console.dir(err);
    }).finally(() => this.$root.$emit('set-loading', false));
  }
};
</script>
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы