尝试通过“ v-for”从vuex渲染数组。
“玩家卡”组件未呈现。 但是“ td”解决方案可以正常工作。
我在JSFiddle上的示例
HTML:
<div id="app">
<button v-on:click="moveItem">
Move Item
</button>
<table cellspacing="2" border="1" cellpadding="5">
<tr>
<td v-for="(item, item_idx) in getItems" v-bind:key="item.col">{{ (item.card)? item.card.name : 'none' }}</td>
</tr>
<tr>
<player-card v-for="(item, item_idx) in getItems" v-bind:key="item.col" v-bind:item="item"></player-card>
</tr>
</table>
<br/>
<p>{{msg}}</p>
</div>
商店:
const store = new Vuex.Store({
state: {
items: [{ col: 0, row: 0 },
{ col: 1, row: 0 },
{ col: 2, row: 0, card: { name: "hello" } } ]
},
getters: {
getterItems: state => { return state.items; }
},
mutations: {
MOVE_ITEM: state => {
state.items[0].card = state.items[2].card;
delete state.items[2].card;
state.message = JSON.stringify(state.items);
}
}
});
组件:
Vue.component('player-card', {
props: {
item: {
type: Object,
required: true
}
},
template: '<td>{{ (item.card)? item.card.name : "none" }}</td>'
});
应用程序:
new Vue({
el: '#app',
store,
data: function() {
return {
msg: ''
}
},
computed: {
getItems() { return this.$store.getters.getterItems; }
},
mounted: function() {
this.msg = JSON.stringify(this.getItems);
},
methods: {
moveItem() {
this.$store.commit('MOVE_ITEM');
this.msg = JSON.stringify(this.getItems);
}
}
});
我已经尝试了许多解决方案,但是还没有找到简单的解决方案。也许有人会提供不同的架构解决方案。
答案 0 :(得分:2)
您只需要更改此行:
<player-card v-for="(item, item_idx) in getItems" v-bind:key="item.col" v-bind:item="item"></player-card>
对此:
<td is="player-card" v-for="(item, item_idx) in getItems" v-bind:key="item.col" v-bind:item="item"></td>
这是必需的,因为您的模板是在DOM中指定的。浏览器将在Vue到达模板标记附近之前解析模板标记。 HTML解析规则仅允许某些元素成为<tr>
的直接子代。其他任何元素将从<table>
中拉出。到Vue解析模板时,<player-card>
元素将已经移至<table>
之外。
如果您使用其他一种技术来指定模板,则不会有问题。
解决方法是使用is
属性指定组件而不是标签名称。
这在这里的文档中进行了解释:
https://vuejs.org/v2/guide/components.html#DOM-Template-Parsing-Caveats
答案 1 :(得分:1)
您需要使用特殊的is
属性来绕过强加的元素结构,其中<tr>
期望<td>
是子元素,但会得到<player-card>
(预先转换)。此外,您对阵列进行变异的方式还会引起反应性问题。考虑我的变化。
const store = new Vuex.Store({
state: {
items: [{
col: 0,
row: 0
},
{
col: 1,
row: 0
},
{
col: 2,
row: 0,
card: {
name: "hello"
}
}
]
},
getters: {
getterItems: state => {
return state.items;
}
},
mutations: {
MOVE_ITEM: state => {
// Move the last element to the front
state.items = [
...state.items.slice(-1),
...state.items.slice(0, -1)
];
state.message = JSON.stringify(state.items);
}
}
});
Vue.component('player-card', {
props: {
item: {
type: Object,
required: true
}
},
template: '<td>{{ (item.card)? item.card.name : "none" }}</td>'
});
new Vue({
el: '#app',
store,
data: function() {
return {
msg: ''
}
},
computed: {
getItems() {
return this.$store.getters.getterItems;
}
},
mounted: function() {
this.msg = JSON.stringify(this.getItems);
},
methods: {
moveItem() {
this.$store.commit('MOVE_ITEM');
this.msg = JSON.stringify(this.getItems);
}
}
});
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vuex"></script>
<div id="app">
<button v-on:click="moveItem">
Move Item
</button>
<table cellspacing="2" border="1" cellpadding="5">
<tr>
<td v-for="(item, item_idx) in getItems" v-bind:key="item.col">{{ (item.card)? item.card.name : 'none' }}</td>
</tr>
<tr>
<td is="player-card" v-for="(item, item_idx) in getItems" v-bind:key="item.col" v-bind:item="item"></td>
</tr>
</table>
<br/>
<p>{{msg}}</p>
</div>
答案 2 :(得分:0)
我的问题也是在vuex中更新数组的问题。
的信息mutations: {
MOVE_ITEM: state => {
// Move card
state.items[0].card = state.items[2].card;
delete state.items[2].card;
// Simple deep array cloning
state.items = JSON.parse(JSON.stringify(state.items));
state.message = JSON.stringify(state.items);
}}
更新了JSFiddle
非常感谢大家。