vue实现条件搜索
实现条件搜索的基本思路
在Vue中实现条件搜索通常涉及以下几个关键步骤:数据绑定、事件监听、过滤逻辑和结果展示。通过组合使用Vue的响应式特性和计算属性,可以高效地完成这一功能。
数据绑定与搜索条件
创建与搜索条件相关的数据属性,通常使用v-model实现双向绑定。例如搜索关键词、多选条件等:
<template>
<input v-model="searchKeyword" placeholder="输入关键词">
<select v-model="selectedCategory">
<option value="">所有分类</option>
<option v-for="cat in categories" :value="cat">{{ cat }}</option>
</select>
</template>
<script>
export default {
data() {
return {
searchKeyword: '',
selectedCategory: '',
categories: ['电子产品', '服装', '食品']
}
}
}
</script>
计算属性实现过滤逻辑
使用计算属性对原始数据进行过滤,这种方式会自动缓存结果,只有当依赖项变化时才会重新计算:
computed: {
filteredItems() {
return this.items.filter(item => {
const matchesKeyword = item.name.toLowerCase().includes(
this.searchKeyword.toLowerCase()
)
const matchesCategory = !this.selectedCategory ||
item.category === this.selectedCategory
return matchesKeyword && matchesCategory
})
}
}
处理复杂条件搜索
对于更复杂的搜索场景,可以拆分为多个步骤:
computed: {
filteredItems() {
let result = [...this.items]
// 关键词搜索
if (this.searchKeyword) {
result = result.filter(item =>
Object.values(item).some(
val => String(val).toLowerCase().includes(
this.searchKeyword.toLowerCase()
)
)
)
}
// 分类筛选
if (this.selectedCategory) {
result = result.filter(
item => item.category === this.selectedCategory
)
}
// 价格范围筛选
if (this.minPrice || this.maxPrice) {
result = result.filter(item => {
const price = item.price
return (!this.minPrice || price >= this.minPrice) &&
(!this.maxPrice || price <= this.maxPrice)
})
}
return result
}
}
性能优化建议
对于大数据量的搜索,可以考虑以下优化方案:
-
添加防抖处理搜索输入:
methods: { debouncedSearch: _.debounce(function() { this.doActualSearch() }, 500) } -
使用Web Worker处理复杂计算
-
分页展示搜索结果,减少一次性渲染的数据量
完整组件示例
<template>
<div>
<input v-model="searchKeyword" @input="handleSearch" placeholder="搜索...">
<select v-model="filters.category">
<option value="">所有分类</option>
<option v-for="cat in categories" :value="cat">{{ cat }}</option>
</select>
<div v-if="isLoading">加载中...</div>
<ul v-else>
<li v-for="item in paginatedItems" :key="item.id">
{{ item.name }} - {{ item.price }}
</li>
</ul>
<div class="pagination">
<button @click="prevPage" :disabled="currentPage === 1">上一页</button>
<span>第 {{ currentPage }} 页</span>
<button @click="nextPage" :disabled="currentPage >= totalPages">下一页</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
searchKeyword: '',
filters: {
category: '',
minPrice: null,
maxPrice: null
},
currentPage: 1,
pageSize: 10,
allItems: [], // 从API获取的原始数据
isLoading: false
}
},
computed: {
filteredItems() {
return this.allItems.filter(item => {
const matchesSearch = !this.searchKeyword ||
item.name.toLowerCase().includes(this.searchKeyword.toLowerCase())
const matchesCategory = !this.filters.category ||
item.category === this.filters.category
return matchesSearch && matchesCategory
})
},
totalPages() {
return Math.ceil(this.filteredItems.length / this.pageSize)
},
paginatedItems() {
const start = (this.currentPage - 1) * this.pageSize
return this.filteredItems.slice(start, start + this.pageSize)
}
},
methods: {
handleSearch() {
this.currentPage = 1 // 搜索时重置到第一页
},
prevPage() {
if (this.currentPage > 1) this.currentPage--
},
nextPage() {
if (this.currentPage < this.totalPages) this.currentPage++
},
async fetchData() {
this.isLoading = true
try {
const response = await api.getItems()
this.allItems = response.data
} finally {
this.isLoading = false
}
}
},
created() {
this.fetchData()
}
}
</script>
与服务端交互
对于大量数据,建议将搜索条件发送到服务端处理:
methods: {
async search() {
try {
const params = {
keyword: this.searchKeyword,
category: this.selectedCategory,
page: this.currentPage,
pageSize: this.pageSize
}
const response = await axios.get('/api/items', { params })
this.items = response.data.items
this.total = response.data.total
} catch (error) {
console.error('搜索失败:', error)
}
}
}






