Javascript 来自子级的VueJS数组操作

Javascript 来自子级的VueJS数组操作,javascript,vue.js,Javascript,Vue.js,我正在处理一个问题,我不知道应该在组件中呈现的项目数组在哪里,但在该组件中,它们可以被操纵到一个新数组中,因此每当对其中一个项目进行更改时,都应该将其推入itemsToEdit数组中,而不是修改原始项,因为以后我需要将新数组发送到服务器,只修改项和字段 “我的孩子”组件有一个简单的复选框(按它应该的方式工作),带有一个checked属性,该属性显示默认值(如果给定),以及一个v-model,包含所有实际工作的逻辑 如果我将v-model设置为v-model=“item.show”它会更改原始项目

我正在处理一个问题,我不知道应该在组件中呈现的项目数组在哪里,但在该组件中,它们可以被操纵到一个新数组中,因此每当对其中一个项目进行更改时,都应该将其推入
itemsToEdit
数组中,而不是修改原始项,因为以后我需要将新数组发送到服务器,只修改项和字段

“我的孩子”组件有一个简单的复选框(按它应该的方式工作),带有一个
checked
属性,该属性显示默认值(如果给定),以及一个
v-model
,包含所有实际工作的逻辑

如果我将
v-model
设置为
v-model=“item.show”
它会更改原始项目,因此其中没有任何更改,但我无法将
项目编辑数组从父级发送给子级,因为该数组为空且
v-model=“items.id.show”
不起作用

我使用过多个复选框和一个数组
v-model
,但这是一个不同的工作流,因为我实际上编辑了原始的项目数组,所以在我选中复选框时它会推送/删除项目,但这不是我想要的,原始数组应该一直保持原样

这是我的简化代码,孩子们实际上有很多复选框,但我只显示一个,因为简单

父组件

<template>
    <div>
        <TestComponent v-for="i in items" :key="i.id" :item="i" :items-to-edit="itemsToEdit"/>
    </div>
</template>

<script>
import TestComponent from '@/TestComponent'
export default {
    name: 'MyParent',
    components: { TestComponent },
    data () {
        return {
            items: [
                { id: 1, name: 'test', show: false },
                { id: 2, name: 'test 2', show: false },
                { id: 3, name: 'test 3', show: true },
                { id: 4, name: 'test 4', show: false }
            ],
            itemsToEdit: []
        }
    }
}
</script>
<template>
    <tr>
        <td>{{ item.id }}</td>
        <td>{{ item.name }}</td>
        <td>
            <MyCheckbox :checked="item.show"/>
        </td>
    </tr>
</template>

<script>
export default {
    name: 'TestComponent',
    components: { MyCheckbox },
    props: ['item', 'itemsToEdit']
}
</script>

从“@/TestComponent”导入TestComponent
导出默认值{
名称:“我的父母”,
组件:{TestComponent},
数据(){
返回{
项目:[
{id:1,名称:'test',show:false},
{id:2,名称:'test2',show:false},
{id:3,名称:'test3',show:true},
{id:4,名称:'test4',show:false}
],
itemsToEdit:[]
}
}
}
子组件

<template>
    <div>
        <TestComponent v-for="i in items" :key="i.id" :item="i" :items-to-edit="itemsToEdit"/>
    </div>
</template>

<script>
import TestComponent from '@/TestComponent'
export default {
    name: 'MyParent',
    components: { TestComponent },
    data () {
        return {
            items: [
                { id: 1, name: 'test', show: false },
                { id: 2, name: 'test 2', show: false },
                { id: 3, name: 'test 3', show: true },
                { id: 4, name: 'test 4', show: false }
            ],
            itemsToEdit: []
        }
    }
}
</script>
<template>
    <tr>
        <td>{{ item.id }}</td>
        <td>{{ item.name }}</td>
        <td>
            <MyCheckbox :checked="item.show"/>
        </td>
    </tr>
</template>

<script>
export default {
    name: 'TestComponent',
    components: { MyCheckbox },
    props: ['item', 'itemsToEdit']
}
</script>

{{item.id}
{{item.name}
导出默认值{
名称:“TestComponent”,
组件:{MyCheckbox},
道具:['item','itemsToEdit']
}
编辑:有一件事我忘记了,我显然可以使用
$emit
在父节点上监听,然后推入数组,但这不是我想要的,我正在寻找一种更好的方法来实现这一点,如果我没有其他选择,我将使用事件


EDIT2:我无法将原始数组“克隆”到
itemsToEdit
中,因为我希望只有在真正发生更改时才填充该数组,因为稍后发送到服务器的请求将只包含真正的更改,如果我发送整个id数组,即使它们没有变化,它也会尝试修改它们,因此这将浪费服务器端的所有性能检查。

无论您选择何种方法,我的建议是将您的列表逻辑保留在一个位置(如果可以的话),以便于维护。有时它们是必要的,但随着它们的扩散,很难使用它们

此外,我不确定这是否是您遇到的问题,但我可以理解,如果您为每个复选框/更改的值创建了不同的事件,
$emit
可能会出现问题。我认为您可以将其整合到一个单独的事件中,如
item updated
,以防止事情变得过于笨拙。例如,在下面的代码片段中,我在每个复选框的输入事件侦听器中使用了一个名为
updateItem
的共享方法,如下所示:
@change=“updateItem({show:$event.target.checked})”
@change=“updateItem({active:$event.target.checked})”。这样,只有一个
$emit
调用(在updateItem方法内部)。试着运行下面的代码段-我认为它应该会给出您想要的结果:

Vue.config.devtools=false
Vue.config.productionTip=false
//父元素
Vue.组件(“v项”{
模板:`
`,
数据(){
常量origItems=[
{id:1,名称:'test',show:false,active:true},
{id:2,名称:'test2',show:false,active:true},
{id:3,名称:'test3',show:true,active:true},
{id:4,名称:'test4',show:false,active:true},
]
返回{
原创性,
items:origItems.map(item=>Object.assign({},item)),
编辑组:[],
}
},
方法:{
项目更新(项目){
const origItem=this.origItems.find(o=>o.id==item.id)
const indexInEdited=this.editedems.findIndex(o=>o.id==item.id)
const objectChanged=JSON.stringify(item)!==JSON.stringify(origItem)
如果(indexInEdited!==-1){
this.editEMS.splice(索引编辑,1)
}
如果(对象已更改){
this.editems.push(项目)
}
//显示编辑列表
控制台清除()
console.log(this.editems)
}
},
})
//子元素
Vue.组件(“v项”{
道具:['item'],
模板:`
{{item.id}
{{item.name}
`,
方法:{
更新项(更新){
//避免通过创建克隆对象直接修改此.item
this.$emit('item-updated',Object.assign({},this.item,update))
}
},
})
新的Vue({el:#app})
console.clear()
正文{
背景:#20262E;
填充:20px;
字体系列:Helvetica;
最小高度:300px;
}
#应用程序{
背景:#fff;
边界半径:4px;
填充:20px;
}
.项目{
显示:网格;
网格自动流:行;
间隙:10px;
}
.项目列表{
显示:网格;
网格模板列:自动1fr自动;
间隙:5px;
}
.项目{
显示:内容;
}

您可以将另一个数组添加到数据中,例如,
currentItems
,并将其初始值作为原始数组的副本。然后,在您的代码中,将
currentItems
替换为
items
,我已经更新了我的