如何使用 vue 3 和 Element Plus ui lib 访问子道具 ref
How to access child prop ref with vue 3 and Element Plus ui lib
我有一个名为 'dropdown'
的下拉组件的引用
当一个项目被选中时,我想得到选中的标签(我可以得到值,但它与标签不同)
当我执行 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>
您可以使用 el-select
的 selected
属性 而不是 selectedLabel
,由于某些原因它似乎总是空白。
selected
属性 包含选定选项的数组(每个包含一个 currentLabel
属性),其中最后一个数组元素是最近选定的。但是,selected
属性 在 change
事件之后更新,因此您必须等待下一个价格变动才能访问它。
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
事件。
我有一个名为 'dropdown'
的下拉组件的引用当一个项目被选中时,我想得到选中的标签(我可以得到值,但它与标签不同)
当我执行 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>
您可以使用 el-select
的 selected
属性 而不是 selectedLabel
,由于某些原因它似乎总是空白。
selected
属性 包含选定选项的数组(每个包含一个 currentLabel
属性),其中最后一个数组元素是最近选定的。但是,selected
属性 在 change
事件之后更新,因此您必须等待下一个价格变动才能访问它。
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
事件。