vuev-用于总是删除最后一个元素,但是设置key不起作用

vshtjzan  于 2023-04-12  发布在  Vue.js
关注(0)|答案(1)|浏览(178)

我有一个应用程序,我想向用户提供一个初始输入,这是一个Map自动完成字段。他们在那里输入一个地址。然后,如果他们愿意,他们可以单击“+”号添加更多字段,如果需要,他们可以删除它们。
模板如下所示:

<div class="address-inputs" v-for="(input, index) in inputs" :key="index">
          <div>
            <label>Enter delivery point:</label>
          </div>
          <GMapAutocomplete @place_changed="setPlace" class="address-input" />
          <button class="btn" v-if="inputs.length > 1" @click="removeInput(index)">Remove</button>
          <div>
            <font-awesome-icon class="handle" icon="fa-solid fa-plus" @click="addInput" />
          </div>
        </div>

数据如下所示:

data() {
    return {
      inputs: [{lat: 0}], // dummy value to get the first input field to show up
    };
  },
  methods: {
    setPlace(place) {
      const input = {
        lat: place.geometry.location.lat(),
        lng: place.geometry.location.lng(),
      };

      this.inputs[this.inputs.length - 1] = input // replace the dummy value with a real address from autocomplete
    },
    addInput() {
      this.inputs.push({lat: 0}); // add another dummy value to get a new blank input field to show up
    },
    removeInput(index) {
      if (index < this.inputs.length) {
        this.inputs.splice(index, 1);
      }

      this.directionsDisplay.setMap(null);
    },

基本上,如果我有:key=index,那么删除就可以从this.inputs中删除正确的地址,但在页面上,它总是从地址列表中删除的最后一个地址。
看起来你应该用一个唯一的标识符来代替:key,但是当我尝试像:key="input.lat"这样的东西时(为了简单起见,我知道我可以concat lat+lng等),地址根本不会出现在自动完成字段中,它只会出现一秒钟,然后消失。
此外,我知道我的setPlace逻辑会中断,例如,如果用户添加了4个地址,然后去更改第二个地址,而不是假设的最后一个地址,但我也不知道如何将索引放入setPlace函数。
下面是一个例子,如果我使用标识符作为密钥,第一个地址就会消失:

<div class="address-inputs" v-for="(input, index) in inputs" :key="`${input.lat}-${input.lng}`">
  <div>
    <label>Enter delivery point:</label>
  </div>
  <font-awesome-icon class="handle" icon="fa-solid fa-bars-staggered" />
  <GMapAutocomplete @place_changed="({ geometry: { location } }) => setPlace(location, index)" class="address-input" />
  <button class="btn" v-if="inputs.length > 1" @click="removeInput(index)">Remove</button>
<p>Here we have lat: {{input.lat}} lng: {{input.lng}} and index: {{index}}</p>
  <div>
    <font-awesome-icon class="handle" icon="fa-solid fa-plus" @click="addInput" />
  </div>
</div>
...
  data() {
    return {
      inputs: [{lat: 0, lng: 0}] // need a blank text GMapAutocomplete field to start
    };
  },
...
  methods: {
    // when this is called, this.inputs is updated properly, with the first address in the first slot at index 0 as expected, but the input disappears from the field instantly, instead of staying

    setPlace({ lat, lng }, index) {
      this.inputs.splice(index, 1, {
        ...this.inputs[index],
        lat: lat(),
        lng: lng()
      })
    },
    addInput() {
      this.inputs.push({lat: 0, lng: 0}); // push the next blank text GMapAutocomplete field to the page for the user to enter in a new address
    },
    removeInput(index) {
      this.inputs.splice(index, 1);
    },

只有当在setPlace()中,I .push()新输入而不是像this.inputs.push({lat: lat(), lng: lng()})那样就地切片时,显示才能工作。然后,地址将如预期的那样留在第一个字段中。但是我有两个问题:
1.下一个输入将自动出现,而不是只在用户点击“+”时才出现
1.与实际的地址值相比,自动完成中的实际输入似乎“偏离一”。我怀疑这与输入消失有关,如果我尝试将其切片到位。请参阅下面的截图,其中包含我已经到位的<p>调试语句:

odopli94

odopli941#

我最终弄明白了这一点。基本上,如果你想删除列表中的正确条目,你不能使用index作为v-for键,这在问题中已经建立了。问题是,我试图使用输入.lat.lng作为键的唯一属性。通常情况下,这会很好,我希望我在我的setPlace()函数中修改了相同的属性。因此,由于我正在主动修改我正在键入的同一个标识符,因此在列表呈现中导致了意外的行为。
解决方案是简单地生成一个随机字符串作为唯一的id,然后将其作为input.id沿着input.latinput.lng附加到我的输入中,然后将其用作我的v-for键。我也不需要做任何特殊的事情来跟踪id,只需在每次推送时为其分配一个唯一的字符串就足以让一切正常工作!

相关问题