Полностью свой Select на Vue 3 (composition api)

Надоело мучиться с переназначением стилей и свойств стандартного Select. На Vue 3 проще сделать СВОЙ и придать ЛЮБОЙ вид этому часто используемому элементу.


Ответы (1 шт):

Автор решения: Михаил
  Доработал для случая нескольких Select

на странице одновременно плюс закрытие при клике в любой области приложения:

    В root giv приложения (отслеживаем клик в любой точке):
    
        <div class="flexColSSnw  h-100" id="AdminView" @click="noSelectsSet">
        <script setup>
         //----------- Selects close/open ------------//
        const selectActive = ref(null)
          provide('selectActive', selectActive)
        const tactSelect = ref(0)
          provide('tactSelect', tactSelect)
        function noSelectsSet() {
          if(tactSelect.value > 0) tactSelect.value = tactSelect.value - 1
          if(tactSelect.value === 0) selectActive.value = null
       }
    
    
    В компоненте:
    ```
    <Select  :selectType="selectType" :selectSubject="selectSubject" :subjects="subjects"  @choseItem="(n) => selectSubject = n></Select>
    ```
    Отдельный модуль (переиспользуемый):
    ```
    <template>
       <div class="flexRawCCnw" :class="selectSubject ? 'selected' : 'selectPS'" @click="setOpen">
          <div  v-if="!selectSubject">Выбрать "{{selectName}}" </div>
          <div v-else>{{selectSubject}} </div>
          <img src="/img/select.png" alt="up" style="height: 0.75rem; margin-left: auto">
       </div>
       <div v-if="selectActive === selectName && tactSelect >0"  class="optionBlock">
          <template v-for="(value, key, index) in subjects">
             <template v-if="selectType === 'object'">
                <div class="selectGroup">{{ key }}</div>
                <template  v-for="item in subjects[key]">
                   <div class="selectOption" @click="send(item, key)">{{ item }}</div>
                </template>
             </template>
             <div v-else class="selectOption" @click="send(value, null)">{{ value }}</div>
          </template>
       </div>
    </template>
    
    <script setup>
    import {ref, defineProps, defineEmits, inject, watch} from "vue"
    
       const props = defineProps(['selectName', 'selectType', 'selectSubject', 'subjects'])
       const emit = defineEmits(['choseItem'])
       const selectActive =inject('selectActive')
       const tactSelect =inject('tactSelect')
    
       function setOpen() {
          if(tactSelect.value === 0) {
             tactSelect.value = tactSelect.value +2
          } else {tactSelect.value = tactSelect.value +1}
          selectActive.value && selectActive.value === props.selectName ? selectActive.value=null : selectActive.value=props.selectName
       }
    
       function send (item, key) {
          emit('choseItem', [item,key])
          selectActive.value = null
       }
    
    </script>
    
    <style scoped>
    
    </style>

```
→ Ссылка