首页 > 解决方案 > 在Vue的子组件中显示添加到数组中的对象

问题描述

在 vue 中,我有一个组件在其父 App.vue 中显示数组的内容。如果我推送到数组,ListofLists 如何让显示列表组件显示更新的数据?

我在子组件中有一个表单,它发出一个由方法 addList 捕获的 javascript 对象 newList。我希望 Vue 能够检测到 ListofList 的更改并重新计算loadedList 的值。如果我的期望是正确的,我如何让 Vue 显示更新的列表?

我应该使用计算还是观看?是否有必要使用 forceRerender 还是问题出在其他地方。

我试过的

<ShowListComponent> 
      :key="componentKey"
      v-bind:loadedList="loadedList"/>

computed: {
      loadedList: function() {
        return this.ListofLists[this.currentList];
    }
  },
  methods: {
    changeList: function(id) {
      this.currentList =  id;
      this.ListofLists[this.currentPlaylist];
      console.log('changed List' + this.ListofLists[this.currentList]);
    },
    addList: function(newList) {
      this.ListofLists.push( newList );
      console.log('lists after push ' +this.ListofLists);
      this.forceRerender();
    },

我看到 的 console.log 显示 ListofLists 已正确更新。

我收到一个错误: [Vue warn]: Error in render: "TypeError: Cannot read property 'name' of undefined"

我的期望 新列表正确显示。

编辑 - 使用的模板和组件

<template>
  <div id="app">
    <MediaPlayer 
      :key="componentKey"
      v-on:openAllSongs="showAllSongs = !showAllSongs" 
      v-on:openPlaylist="showPlaylist= !showPlaylist"
      v-bind:loadedPlaylist="loadedPlaylist"/>
    <AllSongs 
      v-on:closeAllSongs="showAllSongs = false"
      v-bind:songs="playlists[0].songs"
      v-bind:class="{show : showAllSongs}"
    />
    <Playlists 
      v-on:closePlaylist="showPlaylist = false"
      v-bind:playlists="playlists"
      v-bind:class="{show : showPlaylist}"
      v-on:change-playlist="changePlaylist"
      v-on:add-playlist="addPlaylist"
    />
  </div>
</template>

<script>
import MediaPlayer from './components/MediaPlayer.vue'
import Playlists from "./components/Playlists.vue";

export default {
  name: 'App',
  components: {
    MediaPlayer,
    AllSongs,
    Playlists,
  },
  props: ['playlist'],
  data() {
    return {
      playlists: [
        {
          id: 1,
          name: 'All Songs',
          description: 'Magnum Opus',
          created: '18/09/1830',
          updated: '23/04/2020',
          created_by: 'Jamie',
          songs: [
            {
              id: '1',
              position_in_list_index: 47,
              name: 'i dont know what this is but i like it',
              filename: 'i dont know what this is but i like it.mp3',
              length_in_seconds: 200,
              startdate: 'yesterday',
              tags: 'quirky, instumental'
            },
            {
              id:"3",
              position_in_list_index: 38,
              name: "sunday junkie",
              filename: "sunday junkie.mp3",
              length_in_seconds: 222,
              tags: 'indie'
            },
            {
              id: 4,
              position_in_list_index: 40,
              name: "burned",
              filename: "burned.mp3",
              length_in_seconds: 303,
              tags: 'melancholy, serious'
            },
            {
              id: 5,
              position_in_list_index: 46,
              name: "losing limbs like theres no tomorrow",
              filename: "losing limbs like theres no tomorrow.mp3",
              length_in_seconds: 232,
              tags: 'hiphop, dark, synth'
            }

          ],
        },
        {
          id:3,
          name: 'Rock Hard Seduction',
          description: 'songs that bring a tear to your eye',
          created: '21/02/2020',
          updated: '23/03/2020',
          created_by: 'Dewi',
          songs: [  
            {
              id: 4,
              position_in_list_index: 21,
              name: "trefnant rainbow v2",
              filename: "trefnant rainbow v2.mp3",
              length_in_seconds: 174,
              tags: "rock"
            },
            {
              id: 9,
              position_in_list_index: 61,
              name: "trefnant wind added solo",
              filename: "trefnant wind added solo.mp3",
              length_in_seconds: 268,
              tags: 'folk'
            }
          ]
        },
        {
          id:4,
          name: 'Family friendly',
          description: 'they got no lyrics',
          created: '20/02/2020',
          updated: '23/02/2020',
          created_by: 'Dewi',
          songs: [  
             {
                id: "15",
                position_in_list_index: 74,
                name: "dont waltz with a psycho like me",
                filename: "dont waltz with a psycho like me.mp3",
                length_in_seconds: 273
            },
            {
                id: "17",
                position_in_list_index: 76,
                name: "lie down on the tracks",
                filename: "lie down on the tracks.mp3",
                length_in_seconds: 225,
                tags: 'rock, instrumental, sounds like someone else'
            },
            {
                id: "28",
                position_in_list_index: 87,
                name: "you two frozen heroes",
                filename: "you two frozen heroes.mp3",
                length_in_seconds: 267
            }
          ]
        },
      ],
      showPlaylist: false,
      currentPlaylist: 0,
      componentKey: 0
    }
  },
  computed: {
      loadedPlaylist: function() {
        console.log('playlist length in loadedPlaylist ' + this.playlists.length);
        console.log('current playlist id '+ this.currentPlaylist);
        return this.playlists[this.currentPlaylist];
    }
  },
  methods: {
    changePlaylist: function(id) {
      this.currentPlaylist =  id - 1;
      this.playlists[this.currentPlaylist];
      console.log('changed playlist' + this.playlists[this.currentPlaylist]);
    },
    addPlaylist: function(newPlaylist) {
      this.playlists.push( newPlaylist );
      console.log('playlists after push ' +this.playlists);
      this.forceRerender();
      this.changePlaylist(newPlaylist.id);
    },
    forceRerender: function() {
      this.componentKey++;
      console.log("componentKey " + this.componentKey);
    }
  }
}
</script>

我用来显示列表的组件模板。

<template>
  <div class="media-player">

    <draggable  
      v-model="loadedPlaylist.songs" class="songlist" 
      :group="{ name: 'songs'}"
      ghost-class="ghost"
      v-bind:key="loadedPlaylist.id"
    >
          <div 
            class="songlist-item"
            @click='loadTrack(index, true)'
            v-bind:class="{ 'is-active': index === activeTrack }"
            v-bind:key="song.id" 
            v-for="(song, index) in loadedPlaylist.songs"
          >
              <h3>{{index + 1}}. {{song.name}}<span></h3>
          </div>
    </draggable>
  </div>
</template>

标签: vue.jsvuejs2

解决方案


我的代码正确地向数组添加了一个新对象,并且更新正确地传递给了子组件。

我收到一个错误,因为新对象包含一个空数组。试图直接访问它会导致错误。添加

<h2 v-if="loadedPlaylist.songs.length">{{loadedPlaylist.songs[activeTrack].name}}</h2>
    <h2 v-else>Add Songs below</h2>

修复了错误。


推荐阅读