在vue项目中,搜索功能是我们经常需要使用的一个场景,最常用的是在列表数据中搜索一个想要的,今天的例子就是我们实现vue从列表数据中搜索,并展示。如下图所示:
这里我们进行简单搜索功能,搜索逻辑是只要用户输入值与产品的名称进行模糊匹配,符合条件的数据进行展示,不符合条件的数据过滤。流程描述如下:
这张图仅代表最简单的搜索流程,若需要进行一些复杂的处理,可以进行修改,比如说匹配的商品名称关键字变色等。
实现如上图功能,我们肯定是使用vue的组件特性,将搜索以及,产品列表抽成组件,以提高代码复用性,抽成组件之后,该页面将由三个部分组成,数据在以下三个组件之间传递:
父组件:index.vue
<template>
<div>
<title-bar :title="title" @goBack="goback">title-bar>
<search-input
:plhText="searchPlhText"
@input-changed="searchInputChange"
>search-input>
<div v-for="(prd,index) in productListRst" :key="index">
<prd-item :prd="prd" @toPrdDetail="toPrdDetail">prd-item>
div>
div>
template>
<script>
import TitleBar from "@/components/TitleBar";
import SearchInput from "./components/SearchInput";
import PrdItem from './components/PrdItem';
export default {
name: "",
components: {
TitleBar,
SearchInput,
PrdItem
},
data() {
return {
title: "产品列表",
searchPlhText: "请输入产品名称",
productList: {
}, // 产品列表
productListRst: {
}, // 搜索筛选之后的产品列表
}
},
created() {
// 初始化页面参数,按照生命周期,子组件需要的参数父组件需要在created生命周期取值
this.initParams();
},
methods: {
// 返回方法
goback() {
// this.$emit("GoBack");
},
// 初始化页面参数,获取产品列表
initParams() {
this.productList = [
{
imgPath: 'apple-1001.png',
name: 'Apple iPad Air 平板电脑(2020新款)',
price: '4799.00',
sale: '5',
ranking: '10000+评价 平板热卖第5名',
prdShopName: 'Apple官方旗舰店'
},
{
imgPath: 'apple-1002.png',
name: 'Apple iPhone 11手机',
price: '4999.00',
sale: '5',
ranking: '375万+评价',
prdShopName: 'Apple官方旗舰店'
},
{
imgPath: 'apple-1003.jpg',
name: 'Apple AirPods 配充电盒 Apple蓝牙耳机',
price: '1246.00',
sale: '5',
ranking: '200万+评价',
prdShopName: 'Apple官方旗舰店'
},
];
this.productListRst = this.productList;
},
// 每次search框变化则进行筛选,对数据进行逻辑处理
searchInputChange(value) {
// 若未输入值,则展示所有数据
if(null === value || undefined === value){
this.productListRst = this.productList;
} else {
this.productListRst = []; // 结果列表置空
let regStr = '';
// 初始化正则表达式
for(let i=0; i<value.length; i++){
regStr = regStr + '(' + value[i] + ')([\\s]*)'; //跨字匹配
}
let reg = new RegExp(regStr);
console.log(reg);
for(let i=0; i<this.productList.length; i++){
let name = this.productList[i].name; //按照名字匹配
let regMatch = name.match(reg);
if(null !== regMatch) {
// 将匹配的数据放入结果列表中
this.productListRst.push(this.productList[i]);
}
}
}
},
// 去往产品详情页
toPrdDetail(){
this.$router.push({
path: 'detail'})
}
}
};
script>
<style scoped>
#page-title {
width: 100%;
background-color: #fff;
display: flex;
justify-content: center;
}
.backImg {
width: 20px;
}
style>
主要的逻辑处理是 searchInputChange,对于更复杂的搜索逻辑,也可以在里面进行处理。
搜索组件:Search.vue
<template>
<div class="search-box">
<div class="search-input">
<img src="@/assets/images/search.png" />
<input
type="text"
:placeholder="plhText"
maxlength="10"
@change="inputChange"
v-model="inputValue"
/>
</div>
</div>
</template>
<script>
export default {
name: "searchInput", // 搜索输入框
props: {
// input框占位文字
plhText: {
type: String,
default: "请输入搜索内容"
}
},
data() {
return {
inputValue: "" //输入框的值
};
},
methods: {
// 每次输入框变化刷新列表
inputChange() {
// 使用emit给父组件传值
this.$emit('input-changed', this.inputValue);
}
}
};
</script>
列表组件:productList.vue
<template>
<div class="prd-item" @click="toPrdDetail">
<img :src="require('@/assets/images/'+prd.imgPath)">
<div class="prd-discription">
<div class="prd-title">{
{ prd.name }}div>
<div class="prd-sellInfo">
<div class="prd-price">{
{ prd.price }}div>
<div class="prd-saleLable" v-if="prd.sale.lenght!==0">
<label>12期免息label>
<span>新品span>
div>
<div class="prd-ranking">{
{ prd.ranking }}div>
<div class="prd-shop">{
{ prd.prdShopName }}div>
div>
div>
div>
template>
<script>
export default {
props: {
// 传入产品对象,必传属性为imgPath,name,price,shop
prd: {
type: Object,
}
},
methods: {
// 跳转产品详情页面
toPrdDetail() {
this.$emit("to-prd-detail",this.prd.Id);
}
}
};
script>
以上代码为部分代码,css代码不包含在内。
以上代码实现的效果如下动态图: