vue.js - 在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>
解决方案
我的代码正确地向数组添加了一个新对象,并且更新正确地传递给了子组件。
我收到一个错误,因为新对象包含一个空数组。试图直接访问它会导致错误。添加
<h2 v-if="loadedPlaylist.songs.length">{{loadedPlaylist.songs[activeTrack].name}}</h2>
<h2 v-else>Add Songs below</h2>
修复了错误。
推荐阅读
- sql - 可移植的 GROUP BY 子句规则?
- python - Seaborn catplot 与 PairGrid 相结合
- javascript - vue js中的axios将请求作为字符串而不是对象发送
- javascript - 有没有办法在变量名中使用变量?
- regex - Nginx 位置正则表达式通用
- pyspark - 如何使用 rdd.sum() 从 pyspark 中的文本文件中查找 RDD 中特定单词的总数
- c - SDL_Mixer 缺少文件
- python - 基于比较其他数据帧值生成一个带有布尔列的新数据帧
- python - 如何在 python pandas 中删除查询的键值?
- javascript - Vuetify v-progress-linear(不确定)不更新