Как получить доступ к дочернему реквизиту с помощью vue 3 и Element Plus ui lib

У меня есть ссылка на раскрывающийся компонент под названием "раскрывающийся список"

когда элемент выбран, я хочу получить выбранную метку (я могу получить значение, но оно отличается от метки)

когда я делаю dropdown.value, я получаю объект, в котором я могу видеть ключ с нужным мне значением, то есть 'selectedLabel'

если я делаю dropdown.value.selectedLabel, я получаю пустое значение, а dropdown.value.selectedLabel.value не определено.

https://codesandbox.io/s/element-plus-demo-forked-2n982?file=/src/App.vue

Пожалуйста, проверьте изображение, чтобы увидеть шаблон и журналы, которые я получил:

      <template>
  <div class="dropdown-component">
    <div class="label">{{name}}</div>
    <div class="select-container">
      <el-select
        ref="dropdown"
        v-model="selectedValue"
        filterable
        @change="$emit('OPTION_SELECTED', selectedOptionData())"
        :placeholder="placeholderText"
      >
        <el-option
          v-for="(item,index) in options"
          :key="index"
          :label="getLabel(item)"
          :value="getValue(item)"
        >
        </el-option>
      </el-select>
    </div>
  </div>
</template>

<script>
import { ref, defineComponent, watchEffect, computed } from 'vue'
import { getAPIObjFor } from '@/lib/ymm/YMMApi'

export default defineComponent({
  props: {
    labelKey: String,
    valueKey: { type: String, default: '' },
    name: String,
    next: String,
    groupState: Object
  },

  emits: ['OPTION_SELECTED'],

  setup (props) {
    console.log('Initing Dropdown-', props.name)

    const options = ref([])
    const selectedValue = ref('')
    const activeQueryParam = ref('')
    const dropdown = ref(null)
    const apiQueryObj = getAPIObjFor(props.name)

    const getOptionData = async ({ apiQuery, apiRequest }) => {
      // keep log
      console.log('%c' + props.name + ' query:', 'color:orange', apiQuery)
      activeQueryParam.value = apiQuery
      options.value = await apiRequest(apiQuery)
    }

    const getLabel = (_item) => {
      return _item[props.labelKey]
    }

    const getValue = (_item) => {
      const valueKey = props.valueKey === '' ? props.labelKey : props.valueKey
      return { value: _item[valueKey], label: getLabel(_item), x: 'x' }
    }

    const selectedOptionData = () => {
      // eslint-disable-next-line dot-notation
      // eslint-disable-next-line vue/no-ref-as-operand
      // eslint-disable-next-line
      console.log('selected dropdown', dropdown.value, dropdown.value.clearIcon, dropdown.value.selectedLabel)
      const { name } = props
      const { value, label } = selectedValue.value
      const selectedData = {
        [`${name}`]: {
          value,
          label,
          next: props.next
        }
      }
      return selectedData
    }

    const placeholderText = computed(() => {
      return `Select a ${props.name}`
    })

    watchEffect(() => {
      const query = apiQueryObj(props.groupState)
      if (query && query.apiQuery !== activeQueryParam.value) {
        selectedValue.value = ''
        getOptionData(query)
      }
    })

    return { options, getValue, getLabel, selectedValue, selectedOptionData, placeholderText, dropdown }
  }
})
</script>

<style lang="scss" scoped>

.dropdown-component {
  max-width: 500px;
  display: flex;
  flex-direction: row;
  justify-content: space-between;

  .select-container {
    max-width: 400px;
    display: flex;
    min-width: 20px;
    flex-grow: 1;
  }

  .el-select {
    width: 100%;
  }
}

</style>

1 ответ

Решение

Вы можете использовать el-selectсобственность вместо selectedLabel, который по какой-то причине всегда кажется пустым.

Свойство содержит массив выбранных опций (каждая из которых содержит currentLabelproperty), где последний элемент массива выбран последним. Однако selected свойство обновляется после события, поэтому вам нужно дождаться следующего тика, прежде чем обращаться к нему.

      import { nextTick } from 'vue'
//...

const selectedOptionData = async () => {
  await nextTick()
  const selected = dropdown.value.selected.at(-1).currentLabel
  console.log('selectedLabel', selected)
  //...
}

Также ваш @change обработчик событий должен быть изменен на асинхронный, чтобы это работало:

      <el-select @change="onChange">
      export default {
  setup(props, { emit }) {
    const onChange = async () => {
      emit('OPTION_SELECTED', await selectedOptionData())
    }

    return { onChange }
  }
}

демонстрация

Просто имейте в виду, что change-событие также происходит при удалении тега.

Другие вопросы по тегам