vue实现search组件
Vue 实现搜索组件
基础实现
创建一个基础的搜索组件需要包含输入框和搜索逻辑。以下是一个简单的实现示例:
<template>
<div class="search-container">
<input
v-model="searchQuery"
@input="handleSearch"
placeholder="Search..."
/>
<ul v-if="filteredItems.length">
<li v-for="item in filteredItems" :key="item.id">
{{ item.name }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
searchQuery: '',
items: [
{ id: 1, name: 'Apple' },
{ id: 2, name: 'Banana' },
{ id: 3, name: 'Orange' }
],
filteredItems: []
}
},
methods: {
handleSearch() {
this.filteredItems = this.items.filter(item =>
item.name.toLowerCase().includes(this.searchQuery.toLowerCase())
)
}
}
}
</script>
使用计算属性优化
计算属性可以自动响应依赖变化,避免手动触发搜索:
<script>
export default {
data() {
return {
searchQuery: '',
items: [
{ id: 1, name: 'Apple' },
{ id: 2, name: 'Banana' },
{ id: 3, name: 'Orange' }
]
}
},
computed: {
filteredItems() {
return this.items.filter(item =>
item.name.toLowerCase().includes(this.searchQuery.toLowerCase())
)
}
}
}
</script>
添加防抖功能
频繁触发搜索会影响性能,可以使用防抖函数优化:
<script>
import { debounce } from 'lodash'
export default {
data() {
return {
searchQuery: '',
filteredItems: []
}
},
created() {
this.debouncedSearch = debounce(this.doSearch, 300)
},
methods: {
handleSearch() {
this.debouncedSearch()
},
doSearch() {
// 实际搜索逻辑
this.filteredItems = this.items.filter(item =>
item.name.toLowerCase().includes(this.searchQuery.toLowerCase())
)
}
}
}
</script>
支持异步搜索
当需要从API获取搜索结果时:
<script>
export default {
methods: {
async handleSearch() {
if (!this.searchQuery.trim()) return
try {
const response = await axios.get('/api/search', {
params: { q: this.searchQuery }
})
this.searchResults = response.data
} catch (error) {
console.error('Search failed:', error)
}
}
}
}
</script>
样式优化
为搜索组件添加基础样式:
.search-container {
position: relative;
}
input {
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 4px;
width: 200px;
}
ul {
position: absolute;
width: 100%;
max-height: 200px;
overflow-y: auto;
background: white;
border: 1px solid #eee;
margin-top: 4px;
padding: 0;
list-style: none;
}
li {
padding: 8px 12px;
cursor: pointer;
}
li:hover {
background-color: #f5f5f5;
}
组件化封装
将搜索功能封装为可复用组件:
<!-- SearchComponent.vue -->
<template>
<div class="search-component">
<slot name="input" :search="search">
<input
v-model="searchQuery"
@input="handleSearch"
:placeholder="placeholder"
/>
</slot>
<slot name="results" :results="filteredItems">
<ul v-if="showResults && filteredItems.length">
<li
v-for="item in filteredItems"
:key="getKey(item)"
@click="selectItem(item)"
>
{{ getItemText(item) }}
</li>
</ul>
</slot>
</div>
</template>
<script>
export default {
props: {
items: {
type: Array,
required: true
},
placeholder: {
type: String,
default: 'Search...'
},
filterFn: {
type: Function,
default: (item, query) =>
item.text.toLowerCase().includes(query.toLowerCase())
},
getKey: {
type: Function,
default: item => item.id
},
getItemText: {
type: Function,
default: item => item.text
}
},
data() {
return {
searchQuery: '',
showResults: false
}
},
computed: {
filteredItems() {
return this.items.filter(item =>
this.filterFn(item, this.searchQuery)
)
}
},
methods: {
handleSearch() {
this.showResults = true
},
selectItem(item) {
this.$emit('select', item)
this.showResults = false
this.searchQuery = this.getItemText(item)
}
}
}
</script>
使用示例
<template>
<SearchComponent
:items="products"
@select="handleSelect"
placeholder="Search products..."
/>
</template>
<script>
import SearchComponent from './SearchComponent.vue'
export default {
components: { SearchComponent },
data() {
return {
products: [
{ id: 1, name: 'Laptop', price: 999 },
{ id: 2, name: 'Phone', price: 699 }
]
}
},
methods: {
handleSelect(product) {
console.log('Selected:', product)
}
}
}
</script>
这些实现方式涵盖了从基础到高级的搜索组件功能,可以根据实际需求选择适合的方案或组合使用。







