mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-05-11 13:17:29 +08:00
feat: add loading spinner to dropdown
This commit is contained in:
@@ -25,16 +25,23 @@
|
|||||||
<i class="fas fa-search search-icon"></i>
|
<i class="fas fa-search search-icon"></i>
|
||||||
<input type="text" v-model="search" placeholder="搜索" />
|
<input type="text" v-model="search" placeholder="搜索" />
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown-option" v-for="o in filteredOptions" :key="o.id" @click="select(o.id)" :class="{ 'selected': isSelected(o.id) }">
|
<div v-if="loading" class="dropdown-loading">
|
||||||
<img v-if="o.icon" :src="o.icon" class="option-icon" />
|
<l-hatch size="20" stroke="4" speed="3.5" color="var(--primary-color)"></l-hatch>
|
||||||
<span>{{ o.name }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
<template v-else>
|
||||||
|
<div class="dropdown-option" v-for="o in filteredOptions" :key="o.id" @click="select(o.id)" :class="{ 'selected': isSelected(o.id) }">
|
||||||
|
<img v-if="o.icon" :src="o.icon" class="option-icon" />
|
||||||
|
<span>{{ o.name }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'
|
import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'
|
||||||
|
import { hatch } from 'ldrs'
|
||||||
|
hatch.register()
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'BaseDropdown',
|
name: 'BaseDropdown',
|
||||||
@@ -50,6 +57,7 @@ export default {
|
|||||||
const search = ref('')
|
const search = ref('')
|
||||||
const options = ref([])
|
const options = ref([])
|
||||||
const loaded = ref(false)
|
const loaded = ref(false)
|
||||||
|
const loading = ref(false)
|
||||||
const wrapper = ref(null)
|
const wrapper = ref(null)
|
||||||
|
|
||||||
const toggle = () => {
|
const toggle = () => {
|
||||||
@@ -90,11 +98,14 @@ export default {
|
|||||||
watch(open, async val => {
|
watch(open, async val => {
|
||||||
if (val && !loaded.value) {
|
if (val && !loaded.value) {
|
||||||
try {
|
try {
|
||||||
|
loading.value = true
|
||||||
const res = await props.fetchOptions()
|
const res = await props.fetchOptions()
|
||||||
options.value = Array.isArray(res) ? res : []
|
options.value = Array.isArray(res) ? res : []
|
||||||
loaded.value = true
|
loaded.value = true
|
||||||
} catch {
|
} catch {
|
||||||
options.value = []
|
options.value = []
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -119,7 +130,7 @@ export default {
|
|||||||
return selectedLabels.value.some(label => label.id === id)
|
return selectedLabels.value.some(label => label.id === id)
|
||||||
}
|
}
|
||||||
|
|
||||||
return { open, toggle, select, search, filteredOptions, wrapper, selectedLabels, isSelected }
|
return { open, toggle, select, search, filteredOptions, wrapper, selectedLabels, isSelected, loading }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -190,4 +201,10 @@ export default {
|
|||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dropdown-loading {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user