Vue виртуальный DOM не обновляется сразу, когда следует дорогой расчет - PullRequest
0 голосов
/ 17 марта 2019

Я пытаюсь добавить экран загрузки, который отображается, когда мое приложение выполняет дорогостоящее хеширование и дешифрование некоторых данных (занимает 2-3 секунды).Когда я экспериментально удаляю дорогие детали, следуя тому, что должно обновить DOM, экран загружается немедленно.В противном случае, он не рендерится до тех пор, пока дорогая функция не будет завершена.Есть идеи, что я облажался?

export default {
  data(){
    return {
      loading: false,
      password: ''
    }
  },
  methods: {
    async unlock(){
      this.loading = true;
      await this.$nextTick()
      // DOM should update, but it doesn't
      try{
        await this.$root.UnlockVaultPassword(this.password);
      } catch(err){
        this.loading = false;
        return;
      }
      // DOM updates once finished with hashing and ciphering
      this.loading = false;
      this.$router.push({name: 'vault'});
    }
  }
}

Я думаю, что из-за того, что vue обновляет dom асинхронно, я испытываю состояние гонки, когда он не может вписаться в обновление dom среди хэширования.Как я могу ждать, пока дом не будет сделано?

Ответы [ 2 ]

0 голосов
/ 17 марта 2019

Итак, я нашел обходной путь ... Мне это не нравится, но это не так уж ужасно.На самом деле я могу вставить обратный вызов в цикл обработки событий, чтобы мое хэширование происходило только после завершения рендеринга.

export default {
  data(){
    return {
      loading: false,
      password: ''
    }
  },
  methods: {
    async unlock(){
      this.loading = true;
      setTimeout(() => {
        try{
          await this.$root.UnlockVaultPassword(this.password);
        } catch(err){
          this.loading = false;
          return;
        }
        this.loading = false;
        this.$router.push({name: 'vault'});
      }, 0)
    }
  }
}
0 голосов
/ 17 марта 2019

Может быть, попробовать использовать крючок mounted? И вызывайте функцию unlock как отдельную операцию после $nextTick для хорошего разделения проблем.

  mounted () {
    this.loading = true;

    this.$nextTick(function () {
      this.unlock();
    })
  }

  methods: {
    unlock: function() {
      // unlock code
      this.loading = false;
    }
  }

ОБНОВЛЕНИЕ : попробуйте использовать функцию-обработчик, которая сначала устанавливает loading при отправке формы, затем переводит в unlock в качестве обратного вызова $nextTick, например:

  methods: {
    handleFormSubmit: function() {
      this.loading = true;
      this.$nextTick(this.unlock);
    },
    unlock: function() {
      // unlock code
      this.loading = false;
    }
  }

ОБНОВЛЕНИЕ 2 : если ничего из вышеперечисленного не работает, это начинает звучать как ошибка в ожидаемом поведении $nextTick, поскольку рендеринг не завершается до выполнения следующего кода. Что произойдет, если вы используете setTimeout, чтобы принудительно разблокировать процессы до конца стека выполнения?

  methods: {
    handleFormSubmit: function() {
      this.loading = true;
      this.$nextTick(() => {
        setTimeout(this.unlock, 0);
      });
    },
    unlock: function() {
      // unlock code
      this.loading = false;
    }
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...