所以我正在学习Vue.js,经过一番努力,我(不知何故)获得了以下一段代码正在工作。我知道如果它有效,那就太愚蠢了,但是我想知道如何改进我的代码,因为我怀疑我是否采取了正确的方法。
以下代码允许用户通过单击按钮添加Item组件的多个实例。 Item中名称字段的输入传递给一个对象,该对象插入一个数组中,该数组被发送回父组件。
这种方法的主要问题是items数组在作为prop的Item的所有实例之间共享,这是不必要的。但是,我不能提出另一种解决方案,因为我只知道如何通过将它作为prop和更新来共享组件之间的数据。我还读到道具应该只由父母更新,所以我猜测我也违反了这条规则。
有人可以教我一个更好的方法吗?
家长代码
<template>
<div class="items">
<div v-for="n in itemCount">
<Item :count="n" :items="items" />
</div>
</div>
<button @click="addItem">Add item</button>
</template>
<script>
import Item from './../components/Item'; //the child
export default {
components: {
Item
},
data() {
return {
itemCount: 1,
items: [],
}
},
methods: {
addItem() {
this.itemCount ++;
}
}
}
</script>
儿童
<template>
<div class="item">
<label>Item name</label>
<input type="text" v-model="name" @input="update(count)" />
</div>
</template>
<script>
export default {
props: ['items','count'],
data() {
return {
name: '',
}
},
methods: {
createItem(index) {
return {
index: index-1,
name: this.name,
}
},
update(index) {
const item = this.createItem(index);
this.$set(this.items, index-1, item);
},
}
}
</script>
答案 0 :(得分:2)
你对最初的实施感到不舒服是合理的。理想情况下,子组件不应假设其父组件。在这种情况下,子组件只是呈现<label>
和<input>
,以便用户输入项目名称。它不应该知道或关心有多个项目。这是创建这样一个组件的一种方法。它有效地定义了它自己的模型,并简单地将该模型反映到<input>
:
Vue.component('custom-item', {
props: {
value: String
},
template: `
<div class="custom-item">
<label>Item name</label>
<input
type="text"
:value="value"
@input="$emit('input', $event.target.value)"
>
</div>
`
});
然后,父组件只向孩子提供适当的v-model
:(请注意,我已将<button>
移到根元素内,因为模板不能有多个直接子元素元素。)
Vue.component('custom-items', {
data() {
return {
items: []
};
},
methods: {
addItem() {
items.push({
index: items.length,
name: ""
});
}
},
template: `
<div class="custom-items">
<div v-for="item in items">
<custom-item v-model="item.name"/>
</div>
<button @click="addItem">
Add item
</button>
</div>
`
});
该代码对items
对象使用相同的结构,但实际上你似乎不太可能需要.index
属性,在这种情况下items
可能只是一个字符串数组而是比对象。
另外,除非你做一些时髦的风格,否则你实际上并不需要围绕每个自定义项目的<div>
包装器,所以为了简单起见你可能会放弃它:
<div class="custom-items">
<custom-item
v-for="item in items"
v-model="item.name"
/>
<button @click="addItem">
Add item
</button>
</div>
上面可能有一些拼写错误,因为我还没有测试过,但我认为你可以理解。