Vue.js 如何删除该行而不影响其他行

Vue.js 如何删除该行而不影响其他行,vue.js,vuejs2,axios,vue-component,delete-row,Vue.js,Vuejs2,Axios,Vue Component,Delete Row,我正在创建一个可以动态创建行的VueJs父组件,该组件调用另一个可以用axios填充2个下拉列表的组件。 一类 子类别的第二个(此下拉列表可能与第一个下拉列表相关) 这是第一个用于添加行的组件 <template> <div> <ul> <li v-for="(input, index) in inputs" :key="index"> <request-part :index="index" :inp

我正在创建一个可以动态创建行的VueJs父组件,该组件调用另一个可以用axios填充2个下拉列表的组件。 一类 子类别的第二个(此下拉列表可能与第一个下拉列表相关)

这是第一个用于添加行的组件

<template>
  <div>
    <ul>
      <li v-for="(input, index) in inputs" :key="index">
        <request-part :index="index" :input="input" :inputs="inputs">
        </request-part>
        <hr />
      </li>
    </ul>
    <button
      type="button"
      @click="addRow"
      class="btn font-montserrat-regular btn-success btn-plus bt-radius-add"
    >
      Onderdeel toevoegen
    </button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      category: null,
      selectedFile: null,
      subcategory: null,
      current: 0,
      id: 0,
      inputs: [],
      categories: [],
      subcategories: []
    }
  },
  mounted() {
    axios.get('/api/categories').then(res => {
      this.categories = res.data
    })
  },
  created() {
    this.addRow()
  },
  methods: {
    addRow() {
      this.inputs.push({
        category: '',
        subcategory: '',
        sku: '',
        description: '',
        image: ''
      })
    },
    onFileChanged(event) {
      this.selectedFile = event.target.files[0]
    }
  }
}
</script>


昂德代尔·托沃根 导出默认值{ 数据(){ 返回{ 类别:空, selectedFile:null, 子类别:空, 电流:0, id:0, 输入:[], 类别:[], 子类别:[] } }, 安装的(){ get('/api/categories')。然后(res=>{ this.categories=res.data }) }, 创建(){ this.addRow() }, 方法:{ addRow(){ 这是推({ 类别:“”, 子类别:“”, sku:“”, 说明:“”, 图像:“” }) }, onFileChanged(事件){ this.selectedFile=event.target.files[0] } } }
这是填充下拉列表的第二个组件

<template>
  <div class="border-0">
    <div class="row">
      <div class="col-md-8">
        <div class="form-group ml-2">
          <label class="gray-text-color font-montserrat-regular" :for="part">
            {{ $t('labels.frontend.request.part') }} *
          </label>
          <div class="form-group brd3">
            <select
              :name="'r[' + index + '][category]'"
              :id="category + index"
              class="form-control light-gray-background arrow-select-position request-input"
              v-model="input.category"
              @change="onchangeCategorie"
              required
            >
              <option :value="null" disabled selected>
                {{ $t('labels.account.create.selectCategory') }}
              </option>
              <option
                v-for="(option, index1) in categories"
                :value="index1"
                :key="index1"
              >
                {{ option }}
              </option>
            </select>
          </div>
          <div class="form-group brd3">
            <select
              :name="'r[' + index + '][subcategory]'"
              :id="subcategory + index"
              class="form-control light-gray-background arrow-select-position request-input"
              v-model="input.subcategory"
              required
            >
              <option :value="null" disabled selected>
                {{ $t('labels.frontend.request.subCategory') }}
              </option>
              <option
                v-for="(option, index1) in subcategories"
                :value="index1"
                :key="option.id"
              >
                {{ option }}
              </option>
            </select>
          </div>
        </div>
      </div>
      <div class="col-md-4">
        <div class="form-group">
          <label class="gray-text-color font-montserrat-regular" :for="sku">
            {{ $t('labels.frontend.request.articleNumber') }}
          </label>
          <input
            type="text"
            :name="'r[' + index + '][sku]'"
            :id="'sku' + index"
            v-model="input.sku"
            class="form-control light-gray-background request-input"
          />
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-9">
        <div class="form-group" style="margin-right:-40px">
          <input
            type="text"
            :name="'r[' + index + '][description]'"
            v-model="input.description"
            class="form-control light-gray-background input-width-mobile request-input"
            placeholder="Toelichting (optioneel)"
          />
        </div>
      </div>
      <input
        :id="'image' + index"
        :name="'r[' + index + '][image]'"
        type="file"
        class="camera-button inputfile"
        :change="input.image"
        accept="image/*"
        @change="onFileChanged"
      />
      <label :for="'image' + index">
        <img
          src="../../../../../resources/assets/images/cameraIcon.png"
          alt="Camera icon"
          class="camera-button-position"
        />
      </label>
      <div class="pr-l-200 ft-14 mr-3">
        <label>{{ $t('labels.frontend.request.image') }}</label>
      </div>
      <div id="preview">
        <img v-if="url" :src="url" alt="no Image." />
        <button
          v-if="url != null"
          type="button"
          @click="url = null"
          class="btn fa fa-trash btn-default bt-radius"
        ></button>
      </div>
    </div>
    <button
      type="button"
      @click="deleteRow(index)"
      class="btn btn-danger fa fa-trash bt-radius"
    ></button>
  </div>
</template>

<script>
export default {
  props: {
    part: {
      type: String,
      default: null
    },
    sku: {
      type: String,
      default: null
    },
    description: {
      type: String,
      default: null
    },
    image: {
      type: String,
      default: null
    },
    index: {
      type: Number,
      default: 0
    },
    input: {
      type: Object,
      default: () => ({})
    },
    inputs: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      test: null,
      category: null,
      selectedFile: null,
      subcategory: null,
      categories: [],
      subcategories: [],
      url: null
    }
  },
  mounted() {
    axios.get('/api/categories').then(res => {
      this.categories = res.data
    })
  },
  methods: {
    deleteRow(index) {
      console.log(index)
      this.$delete(this.inputs, index)
    },
    onFileChanged(event) {
      this.selectedFile = event.target.files[0]
      this.input.image = this.selectedFile
      this.url = URL.createObjectURL(this.selectedFile)
    },
    onchangeCategorie(e) {
      axios.get('/api/categories/' + e.target.value).then(res => {
        this.subcategories = res.data
      })
    }
  }
}
</script>
<style>
#preview {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: auto;
}
#preview img {
  max-width: 200px;
  max-height: 200px;
  border-radius: 5px;
  border: 1px solid lightgray;
}
</style>

{{$t('labels.frontend.request.part')}*
{{$t('labels.account.create.selectCategory')}
{{option}}
{{$t('labels.frontend.request.subCategory')}
{{option}}
{{$t('labels.frontend.request.articleNumber')}
{{$t('labels.frontend.request.image')}
导出默认值{
道具:{
第部分:{
类型:字符串,
默认值:null
},
sku:{
类型:字符串,
默认值:null
},
说明:{
类型:字符串,
默认值:null
},
图片:{
类型:字符串,
默认值:null
},
索引:{
类型:数字,
默认值:0
},
输入:{
类型:对象,
默认值:()=>({})
},
投入:{
类型:数组,
默认值:()=>[]
}
},
数据(){
返回{
测试:空,
类别:空,
selectedFile:null,
子类别:空,
类别:[],
子类别:[],
url:null
}
},
安装的(){
get('/api/categories')。然后(res=>{
this.categories=res.data
})
},
方法:{
删除行(索引){
console.log(索引)
this.$delete(this.inputs,index)
},
onFileChanged(事件){
this.selectedFile=event.target.files[0]
this.input.image=this.selectedFile
this.url=url.createObjectURL(this.selectedFile)
},
onchangeCategorie(e){
get('/api/categories/'+e.target.value)。然后(res=>{
this.subcategories=res.data
})
}
}
}
#预演{
显示器:flex;
证明内容:中心;
对齐项目:居中;
保证金:自动;
}
#预览img{
最大宽度:200px;
最大高度:200px;
边界半径:5px;
边框:1px实心浅灰色;
}
当我试图从上到下删除第一行或任何一行时,所有子类别都消失了。
当我从下到上删除行时,它工作正常

您的问题是因为您的行没有正确的稳定唯一ID,而是使用它们的数组索引作为
指令中的
:键
。这是一个问题的原因,因为当您使用
$delete()
从数组中删除一个元素时,所有后面的元素都会下移到一个新的较低的索引,以便数组保持连续

解决方案是为行提供一个唯一的ID。一个简单的全局计数器就可以了:

var计数器=0;//行ID(或任何其他需要行ID的对象)的全局计数器
导出默认值{
// ...
方法:{
addRow(){
这是推({
类别:“”,
子类别:“”,
sku:“”,
说明:“”,
图像:“”,
id:++counter//这为每行提供了一个不同的id号
})
},
// ...
}
然后,您可以在
v-for
指令中将此唯一ID用作
:键



  • 我打赌您的问题与使用
    :key=“index”有关
    。这通常是个坏主意。你的行中真的没有任何稳定的唯一标识符可以用作正确的键吗?我没有使用任何唯一标识符,你有这样的例子吗?是的,这是固定的,非常感谢。我在单击“添加行”时添加了一个计数器,它会递增,然后我将其作为键添加。谢谢你帮我节省了一天的时间