VueJs: обертывание el-select: элементы списка добавляются 3 раза во время обновления DOM

Я инкапсулировал некоторые из превосходных компонентов element-ui. . Поскольку я обычно использую одни и те же настройки повсюду. Плюс я хотел иметь более чистый код. Все работает нормально, кроме el-select, где я получаю ошибку DOM о дублирующихся ключах.

[Vue warn]: Duplicate keys detected: 'XXX VALUE'. This may cause an update error.

введите здесь описание изображения

Первоначально я просто передал список прямо в <el-select>, получил те же ошибки, затем сделал localList var, то же самое.

Я добавил nextTick в раздел монтирования, здесь есть полный пример.

Содержимое списка добавляется 3 раза, отсюда и ошибка. введите здесь описание изображения

// Please note: The original code is a .vue component, modified it for this example.

Vue.component('select-input', {
  props: {
    label: {
     type: String,
     default: 'Select'
    },

  value: {
      required: true
    },

    list: {
      type: Array,
      default: null
    },
    
    disabled: {
     type: Boolean,
     default: false
    }
  },

  methods: {
    init () {
      this.localList = this.list
    },

    updated (value) {
      this.form = value
      this.$emit('input', this.form)
      this.$emit('change', this.form)
    }
  },

  data () {
    return {
      form: this.value,
      localList: []
    }
  },


  mounted () {
    this.$nextTick().then(this.init())
  },

  template: '<el-form-item :label="label" v-if="localList"><el-select v-if="!disabled" v-model="form" placeholder="Select..." :disabled="disabled" @change="updated"><el-option v-if="item[valueKey]" v-for="item in localList" :label="item[labelValue]":value="item[valueKey]" :key="item[valueKey]" /><el-option v-else v-for="(item, index) in list" :label="item" :value="item" :key="index" /></el-select> <b v-else>{{this.form}}</b></el-form-item>'
})

var app = new Vue({
  el: '#app',
  data: {
    select1: null,
    select2: null,
    list: ['Minutes', 'Hours', 'Days']
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<!-- import CSS -->
<link rel="stylesheet" href="https://unpkg.com/[email protected]/lib/theme-chalk/index.css">
<!-- import JavaScript -->
<script src="https://unpkg.com/[email protected]/lib/index.js"></script>

<body>

<div id="app">
  <h3>Normal Select Works OK</h3>
  <el-select v-model="select1" placeholder="Select...">
    <el-option v-for="item in list" :value="item" :key="item"></el-option>
  </el-select>
 
  <p>You chose: <b>{{select1}}</b></p>
  
  <hr />

  <h3>Wrapped Component Select Works Gives Errors</h3>
  <p><i>See browser console</i></p>

  <el-form>
    <select-input label="Period" v-model="select2" :list="list"></select-input>
  </el-form>
  <p>You chose: <b>{{select2}}</b></p>
  

</div>



</body>


person Anthony    schedule 14.09.2019    source источник
comment
Может быть, что-то еще портит список, внешнее по отношению к предоставленному коду? Путей расследования множество, но все они начинаются с выяснения того, не искажается ли сам массив. Попробуйте использовать Object.freeze, чтобы остановить его изменение. Попробуйте выгрузить его в шаблон, используя {{ list }}. Что, если вместо этого использовать this.localList = ['Minutes', 'Hours', 'Days']? Порядок на картинке отличается от кода (M/H/D, а не H/M/D). Не совсем понятно, почему вы используете псевдонимы list для localList, они оба будут ссылаться на один и тот же объект, поэтому изменение одного изменит другое.   -  person skirtle    schedule 14.09.2019
comment
Спасибо за предложения @skirtle, порядок в списке другой просто потому, что я набрал их в этом порядке для примера. Хороший улов однако. Я проверил целостность списка, он не меняется, происходит то, что ‹el-option› вызывается 3 раза с одними и теми же данными из-за моего условия v-if (которого нет в примере), я подозреваю.   -  person Anthony    schedule 14.09.2019


Ответы (2)


попробуй это

ваш ключ цикла v-for является элементом, попробуйте изменить его на такой индекс

<el-option v-for="(item, index) in localList" :label="item" :value="item" :key="index" /> </el-select>
person sid heart    schedule 14.09.2019
comment
спасибо, sid heart только что попробовал - теперь я получаю Duplicate keys detected: '0'. This may cause an update error и так далее для каждого ключа. - person Anthony; 14.09.2019
comment
Я вроде как понял это, я исключил из примера v-if и v-else вокруг того, является ли это простым списком или структурированным списком объектов. это, кажется, вызывает проблемы. - person Anthony; 14.09.2019

Нашел - как и предполагалось, проблема была в условии v-else. Поскольку с простым списком, а не с массивом объектов с меткой и парами значений, это будет соответствовать условию else.

<el-option v-if="item[valueKey]" v-for="item in localList"
 :label="item[labelValue]":value="item[valueKey]" :key="item[valueKey]" />

<el-option v-else v-for="(item, index) in list"
  :label="item" :value="item" :key="index" />

Если компонент получает простой список, он теперь обрабатывает его, чтобы его можно было обработать следующим образом:

<el-option v-for="item in localList"
 :label="item[labelValue]":value="item[valueKey]" :key="item[valueKey]" />

Наверное, я пытался быть слишком умным наполовину!

person Anthony    schedule 14.09.2019