Как получить доступ к дочернему реквизиту с помощью 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
, который по какой-то причине всегда кажется пустым.
Свойство содержит массив выбранных опций (каждая из которых содержит
currentLabel
property), где последний элемент массива выбран последним. Однако
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
-событие также происходит при удалении тега.