Проблема: повторный рендеринг экземпляра vue при изменении данных обратным вызовом внутри метода

#javascript #vue.js #electron

#javascript #vue.js #electron

Вопрос:

Я разрабатываю приложение с electron, используя vue.js как автономный libray (без использования CLI), и он получает довольно странное поведение повторного рендеринга, когда я изменяю данные обратным вызовом метода electron внутри метода vue (рендеринг на v-for). Я показываю упрощенный код:

 
<div class="list-item" v-for="(filePath, index) in playlistArray">
   <div class="audio-file-index"> {{ index   1 }} </div>
   <div class="audio-file-name"> {{ filePath }} </div>
</div>

  
 const { remote } = require('electron');

let vue = new Vue({
  el: '#app',
  data: {
    playlistArray: ['', '', '', '', '']
    // could just '= Array(5)' but i need '' elements so the v-for renders 5 
    // empty divs right away
  },
  methods: {
    addAudioFile() {

      remote.dialog.showOpenDialog({ // electron.remote method to let user select files

        //... doesn't metter, just a options object....

      }, (pathArray) => {
         // pathArray returns a array with all paths selected by the user

         let j = 0;
         for(i = 0; i < this.playlistArray.length; i  ) {
            if(this.playlist[i] == '') {
               this.playlistArray[i] = pathArray[i   j];
               j  ;
            }
         }
      })
    }
  }
})
  

Хорошо, итак, когда пользователь выбирает аудиофайлы, divs показывают путь и (индекс 1) каждого пути.

Первое, чего я не получаю: после первого вызова addAudioFile( ) все ‘ ‘ элементы playlistArray становятся неопределенными, поэтому мне пришлось изменить параметр состояния if на:

 if(this.playlistArray[i] == '' || this.playlistArray[i] == undefined)
  

Почему это меняется? (Если в массиве есть элемент с правдивой строкой, он не меняется на неопределенный). Но ладно…

Поведение wird: v-for не выполняет повторный рендеринг при изменении playlistArray … но…Если я использую инструменты разработчика, закрываю его и щелкаю в любом месте моего приложения, повторный рендеринг работает (?).

Я изменил код, используя другой справочный метод и справочную переменную:

 
...

let vue = new Vue({
  el: '#app',
  data: {
    playlistArray: ['', '', '', '', '']
  },
  methods: {
    addAudioFile() {

      remote.dialog.showOpenDialog({

        ...

      }, (pathArray) => {
         let j = 0;
         let newPlaylistArray = [];

         for(i = 0; i < this.playlistArray.length; i  ) {
            if(this.playlist[i] == '' || this.playlistArray[i] == undefined) {
               newPlaylistArray[i] = pathArray[0   j];
               j  ;
            }
            else newPlaylistArray[i] = this.playlistArray[i] || '';
         }
         this.updatePlaylist(newPlaylistArray);
      })
    },

     updatePlaylist(playlist) {
        this.playlistArray = playlist;
     }
  }
})

  

… и теперь это работает должным образом. Почему?

Ответ №1:

Я предполагаю, что из-за реактивности. Как говорится в документации:

Vue не может обнаружить следующие изменения в массиве:

  • Когда вы напрямую задаете элемент с индексом, например
    vm.items[indexOfItem] = newValue

Источник


Чтобы заставить ваш первый пример работать, вы можете попробовать методы splice или set :

 for(i = 0; i < this.playlistArray.length; i  ) {
  if(this.playlist[i] == '') {
    this.playlistArray.splice(i, 1, pathArray[i   j])
    // or
    this.$set(this.playlistArray, i, pathArray[i   j])
    j  ;
  }
}
  

Примечание: вы используете это условие if(this.playlist[i] == '') . Откуда playlist берется свойство? Вы имеете в виду playlistArray вместо этого?

Комментарии:

1. Спасибо! Это работает. И да, здесь я допустил ошибку, я имел в виду playlistArray.