vue实现search组件
Vue 实现搜索组件
基本结构
使用 Vue 的单文件组件(SFC)结构,包含模板、脚本和样式部分。模板部分定义搜索框和结果列表,脚本部分处理搜索逻辑,样式部分定义组件外观。
<template>
<div class="search-container">
<input
v-model="searchQuery"
@input="handleSearch"
placeholder="输入关键词搜索..."
/>
<ul v-if="searchResults.length">
<li v-for="result in searchResults" :key="result.id">
{{ result.name }}
</li>
</ul>
<p v-else-if="searchQuery && !searchResults.length">无匹配结果</p>
</div>
</template>
数据与逻辑
定义搜索查询和结果数据,实现搜索方法。可以使用计算属性或方法过滤数据。
<script>
export default {
data() {
return {
searchQuery: '',
searchResults: [],
items: [
{ id: 1, name: 'Vue.js' },
{ id: 2, name: 'React' },
{ id: 3, name: 'Angular' }
]
}
},
methods: {
handleSearch() {
if (!this.searchQuery) {
this.searchResults = [];
return;
}
const query = this.searchQuery.toLowerCase();
this.searchResults = this.items.filter(item =>
item.name.toLowerCase().includes(query)
);
}
}
}
</script>
样式优化
添加基础样式提升用户体验,包括输入框和结果列表的样式。
<style scoped>
.search-container {
max-width: 400px;
margin: 0 auto;
}
input {
width: 100%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
ul {
list-style: none;
padding: 0;
margin-top: 10px;
}
li {
padding: 8px;
border-bottom: 1px solid #eee;
}
</style>
异步搜索支持
对于需要从API获取数据的场景,可以使用异步方法。
methods: {
async handleSearch() {
if (!this.searchQuery) {
this.searchResults = [];
return;
}
try {
const response = await fetch(`/api/search?q=${this.searchQuery}`);
this.searchResults = await response.json();
} catch (error) {
console.error('搜索失败:', error);
}
}
}
防抖优化
通过防抖减少频繁请求,提升性能。
import { debounce } from 'lodash';
export default {
methods: {
handleSearch: debounce(function() {
// 搜索逻辑
}, 300)
}
}
组件复用
通过props接收外部数据,通过emit事件通知父组件搜索结果。
props: {
items: {
type: Array,
required: true
}
},
methods: {
handleSearch() {
// 搜索逻辑
this.$emit('search-results', this.searchResults);
}
}
完整示例
结合以上要点,实现一个完整的可复用搜索组件。
<template>
<div class="search-component">
<input
v-model="searchQuery"
@input="handleSearch"
placeholder="搜索..."
/>
<slot :results="searchResults">
<ul v-if="searchResults.length">
<li v-for="result in searchResults" :key="result.id">
{{ result.text }}
</li>
</ul>
</slot>
</div>
</template>
<script>
import { debounce } from 'lodash';
export default {
props: {
items: Array,
searchKey: {
type: String,
default: 'text'
}
},
data() {
return {
searchQuery: '',
searchResults: []
}
},
methods: {
handleSearch: debounce(function() {
if (!this.searchQuery) {
this.searchResults = [];
return;
}
const query = this.searchQuery.toLowerCase();
this.searchResults = this.items.filter(item =>
String(item[this.searchKey]).toLowerCase().includes(query)
);
this.$emit('results', this.searchResults);
}, 300)
}
}
</script>






