Select Component Design Document
Overview
The Select component is an interactive component in this component library used for dropdown selection. It continues the consistent design philosophy of our component library, adopting the principles of "separation of concerns" and "logic abstraction." It implements a complete and easy-to-use dropdown selection solution through core logic such as useStyleComputed.
The Select component focuses on handling users' option selection operations, providing an intuitive and visually appealing dropdown selection feature that supports custom sizes, disabled state, scrollbar control, and option highlighting.
Design Philosophy
Layered Architecture
The Select component strictly follows a three-layer architecture design:
- Structure Layer select.vue, option.vue - Responsible for the component's DOM structure and basic layout
- Logic Layer select.ts - Handles complex reactive computations and interaction logic
- Presentation Layer select.scss, option.scss - Defines the component's visual presentation and style rules
Logic Abstraction
The Select component abstracts complex logic into core functions:
- useStyleComputed - Handles style computation
- Dependency injection mechanism - Implements parent-child component communication
This design allows the component itself to only declare the required logic, while the specific computations are handled by the logic functions.
Core Feature Design
Structured Props Design
The props design of the Select component is concise and clear:
export const selectProps = {
modelValue: {
type: [String, Number] as PropType<SelectValue>,
default: ''
},
placeholder: {
type: String,
default: '请选择'
},
disabled: {
type: Boolean,
default: false
},
width: {
type: [String, Number] as PropType<SelectSize>,
default: '260px'
},
height: {
type: [String, Number] as PropType<SelectSize>,
default: '40px'
},
backgroundColor: {
type: String,
default: ''
},
hoverbackgroundColor: {
type: String,
default: ''
},
borderColor: {
type: String,
default: ''
},
autoScrollbar: {
type: Boolean,
default: true
}
};This design provides sufficient flexibility and supports multiple usage scenarios.
Dependency Injection Mechanism
The Select component implements parent-child component communication through Vue's dependency injection mechanism:
// Provide context
provide('select', {
selectOption,
currentValue: computed(() => props.modelValue),
disabled: computed(() => props.disabled),
width: computed(() => props.width),
height: computed(() => props.height)
})
// Inject context
const ctx = inject<SelectContext>('select')
if (!ctx) {
throw new Error('MYOption must be used inside MYSelect')
}This design enables seamless collaboration between the Option component and its parent Select component.
Style System Design
CSS Variable Control
The Select component implements style control through CSS variables:
--text-color- Text color--dropdown-bg-color- Dropdown background color--hover-bg-color- Hover background color--active-color- Active state color--option-bg-color- Option background color--option-hover-bg-color- Option hover background color
Size System
The Select component supports flexible size control:
- Default Size - 260px × 40px
- Custom Size - Supports px, em, % and other units
- Responsive Design - Supports adaptation to different screen sizes
State Styles
The Select component provides corresponding styles according to different states:
- Default State - Standard dropdown style
- Hover State - Style when mouse hovers
- Focus State - Style when focused
- Disabled State - Semi-transparent effect when disabled
- Expanded State - Arrow rotation effect when the dropdown is expanded
Component Structure Design
Overall Structure
The overall structure of the Select component is as follows:
<div class="select-e" :class="{
'is-disabled': disabled,
'is-focused': isFocused
}" tabindex="0" :style="selectStyle" @focus="handleFocus" @blur="handleBlur">
<div class="select-trigger" @click="toggleDropdown">
<span class="selected-value">{{ selectedLabel || placeholder }}</span>
<span class="arrow-icon" :class="{ 'is-open': dropdownVisible }">
<svg viewBox="0 0 24 24" width="16" height="16">
<path d="M7 10l5 5 5-5z" />
</svg>
</span>
</div>
<Transition name="slide-fade">
<div v-if="dropdownVisible" ref="dropdownRef" class="select-dropdown">
<MYScrollbar v-if="showScrollbar" height="200px" thumbColor="#4C4D4F" thumbHoverColor="#2a2a2e"
trackColor="#2a2a2e">
<slot></slot>
</MYScrollbar>
<div v-else class="select-dropdown-content">
<slot></slot>
</div>
</div>
</Transition>
</div>Option Structure
The structure of the Option component is as follows:
<div
class="select-option"
:class="{
'is-selected': isSelected,
'is-disabled': disabled
}"
:data-value="value"
:data-label="label || value"
@click="handleClick"
>
<slot>{{ label }}</slot>
</div>Interaction Design
Dropdown Expand/Collapse
The Select component supports clicking to expand/collapse the dropdown:
const toggleDropdown = () => {
if (props.disabled) return
dropdownVisible.value = !dropdownVisible.value
if (dropdownVisible.value) {
checkScrollbarVisibility()
// Recalculate selected label when dropdown is opened
updateSelectedLabel()
}
}Option Selection
The Option component supports clicking to select an option:
const handleClick = () => {
if (!props.disabled && !selectDisabled.value) {
selectOption(props.value, props.label || String(props.value))
}
}Scrollbar Control
The Select component supports automatic scrollbar control:
const checkScrollbarVisibility = () => {
nextTick(() => {
if (!props.autoScrollbar) {
showScrollbar.value = false
return
}
if (dropdownRef.value) {
const content = dropdownRef.value.querySelector('.select-dropdown-content') || dropdownRef.value
const contentHeight = (content as HTMLElement).scrollHeight
showScrollbar.value = contentHeight > 190
}
})
}Extensibility Design
The Select component has excellent extensibility:
- Custom Size: Control component size through width and height properties
- Disabled State: Control disabled state through the disabled property
- Scrollbar Control: Control scrollbar display through the autoScrollbar property
- Style Customization: Control styles through properties such as backgroundColor, hoverbackgroundColor, and borderColor
- Option Customization: Support custom option content through slots
- Theme Adaptation: Supports theme customization through CSS variables
Style Details
The Select component has the following characteristics in style handling:
- Transition Animation: Smooth transition effects when the dropdown expands/collapses
- Responsive Design: Supports flexible size adaptation
- Accessibility Design: Supports keyboard navigation and screen readers
- Consistency: Maintains style consistency with other form components in the component library
- Highlighting: Selected options have obvious highlight effects
Performance Optimization
Performance is optimized through the following methods:
- Use computed properties to cache calculation results
- Move complex logic to independent functions
- Avoid unnecessary re-renders
- Use Vue 3 Composition API to improve runtime efficiency
- Reasonably add and remove event listeners
- Delay scrollbar visibility calculation
Design Value
The Select component continues the design philosophy of our component library:
- Separation of concerns: Structure, styles, and logic are completely decoupled
- High reusability: Abstract common logic through functions
- Easy maintenance: Clear code structure and naming conventions
- Strong extensibility: Supports rich customization options
- Consistency: Maintains a consistent design language with other components such as PickColor, Rate, Switch, Checkbox, and Radio