接上文继续实现点餐页面。回看前一篇文章,发现搜索框样式布局已经实现,但是逻辑部分忘记写了,所以本篇文章就以搜索框逻辑开篇。
首先看一下搜索页面的示意图
1、搜索页面布局与功能实现
首先需要注意的一点是,点餐页面最上方的搜索框是一个"死框",即仅仅是一个点击跳转至搜索页面的"装饰",并没有搜索功能。
同样,样式布局就不过多解释,直接放源码,有需要的自己复制
<view style="padding-bottom: 10rpx;">
<view class="search-input">
<image src="https://7761-waimai-user-6g2zcvhp46ac02a8-1326568420.tcb.qcloud.la/static/diandan/sousuo.png?sign=fd87793ca3d569294b92116ce843fb1b&t=1719890621" mode="aspectFill"></image>
<view @click="search" class="custom-button">搜索</view>
<!-- @confirm="search"是可以实现点击键盘的搜索也能进行商品检索 -->
<input type="text" @confirm="search" :focus="true" v-model="keyword.data" placeholder=""
confirm-type="search"/>
</view>
</view>
.search-input{
background: #FFFFFF;
font-size: 28rpx;
display: flex;
flex-direction: row;
flex: 1;
position: relative;
align-items: center;
height: 90rpx;
width: 100%;
}
.search-input image:nth-child(1){
border-radius: 50upx;
width: 35rpx;
height: 35rpx;
position: absolute;
left: 50rpx;
align-self: center;
}
.search-input input{
background-color: #f4f4f4;
width: 100%;
color: #b2b2b2;
padding-left: 80upx;
padding-right: 75px;
border-radius: 50rpx;
height: 60rpx;
margin-left: 20rpx;
}
.custom-button{
/* 48*27 */
position: absolute;
top: 50%;
right: 0;
font-size: 25rpx;
transform: translateY(-50%);
background-color: #81614A; /* 红色背景 */
color: #fff;
padding: 4px 10px;
border-radius: 15px; /* 边框弧度 */
cursor: pointer;
user-select: none;
margin-right: 5px; /* 设置按钮与输入框的间距 */
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
outline: none;
}
1.1、搜索功能实现
先放代码:
// 触发搜索
async function search(){
// 本地缓存搜索历史
if(keyword.data==''){
const res = await db.collection('goods').get()
card.value = res.data
}
let search_arr = wx.getStorageSync('search_key') || [] //取出本地缓存记录
var specialCharacters = /[!@#$%^&*(),.?":{}|<> ]/
if(keyword.data!=''&& !specialCharacters.test(keyword.data)){
search_arr.unshift(keyword.data) //unshift()函数是将值插入到数组的前端
wx.setStorageSync('search_key',search_arr)
}
card.value=[]
data_search()
}
// 数据库模糊查询
async function data_search(){
wx.showLoading({title:'加载中...',mask:true})
// load_data.loaded=false
// 设置模糊字段匹配
let query = _.or([
{
category:db.RegExp({
regexp:keyword.data,
options:'i'
})
},
{
goods_title:db.RegExp({
regexp:keyword.data,
options:'i'
})
}
])
const res = await db.collection('goods').where(query).get()
show_history.value = false
card.value = res.data
if(card.value.length===0){
show_1.value = true
}else{
show_1.value = false
}
wx.hideLoading()
}
说一下思路:在输入关键字后点击搜索,是根据搜索的关键字在数据库"goods"中提取"分类"、"商品标题"中含有关键字的商品,具体实现如方法data_search()。搜索过的关键字会存储在本地,以便在"历史记录"中展示。(复制完无法直接使用,需要创建对应的响应式变量,例如card、show_history、show_1。)
如何创建本地存储:
wx.setStorageSync('search_key',search_arr)
1.2、商品列表布局
同样,直接放代码,就不过多解释
<view class="goods_view" v-for="(item,index) in card" :key="index" @click="show_details(item._id)">
<view class="goods_before">
<view class="goods_image">
<image :src="item.goods_cover" mode="aspectFill"></image>
</view>
<view class="goods_title overflow">{{item.goods_title}}</view>
</view>
<view class="goods_price">
<view class="price_view">
<text>¥ </text>
<text>{{getInt(item.goods_price)}}</text>
<text>.{{getDec(item.goods_price)}}</text>
</view>
</view>
</view>
<view style="height: 100rpx;"></view>
<view class="centered-container" v-if="card.length==0 && show_history == false && show_1">
<image class="img" src="https://7761-waimai-user-6g2zcvhp46ac02a8-1326568420.tcb.qcloud.la/static/other/none_data.png?sign=e6636bc868bfbebec9d33cb1081baa23&t=1723096179" mode="aspectFill"></image>
<view class="text">
没找到对应商品,再看看~
</view>
</view>
对应的css样式:
.goods_view{
background-color: #FFFFFF;
padding: 10rpx 20rpx;
margin: 10rpx 15rpx;
border-radius: 10rpx;
display: flex;
justify-content: space-between;
}
.goods_before{
display: flex;
}
.goods_image{
width: 100rpx;
height: 100rpx;
padding: 5rpx;
}
.goods_image image{
width: 100rpx;
height: 100rpx;
border-radius: 10rpx;
}
.goods_title{
font-size: 28rpx;
font-family: "黑体";
margin-left: 20rpx;
display: flex;
align-items: center;
}
.overflow{
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
.goods_price{
display: flex;
align-items: center;
}
.price_view{
display: flex;
font-size: 28rpx;
margin-right: 10rpx;
font-weight: bold;
}
.centered-container{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
width: 200px;
height: 200px;
margin-top: -50px;
}
.img {
width: 200px;
height: 200px;
display: block;
}
.text {
margin-top: 20px;
text-align: center;
color: #999;
}
2、历史记录布局与功能实现
2.1、历史记录布局
直接放代码
<block v-if="history.length>0 && show_history">
<view class="history">
<text>历史记录</text>
<image src="../../static/search/shanchu.svg" mode="aspectFill" @click="del"></image>
</view>
<view class="history-text">
<text v-for="(item,index) in history" :key="index" @click="history_search(item)">{{item}}</text>
</view>
</block>
注意,上面有些响应式变量需要自己创建,同时有一些静态文件,自己在网上找一下对应的图标进行替换。
推荐一个图标网站: iconfont-阿里巴巴矢量图标库
对应的CSS样式:
.history image{
display: block;
width: 30rpx;
height: 30rpx;
}
.history{
display: flex;
align-items: center;
justify-content: space-between;
margin: 40rpx 20rpx;
font-size: 30rpx;
font-weight: bold;
font-family: "黑体";
}
.history-text{
display: flex;
flex-wrap: wrap;
margin: 0 20rpx;
}
.history-text text{
background-color: #FFFFFF;
margin: 0 20rpx 20rpx 0;
border-radius: 7rpx;
padding: 10rpx 20rpx;
font-size: 28rpx;
font-family: "黑体";
}
2.2、历史记录功能实现
// 点击搜索历史记录触发搜索
function history_search(item){
keyword.data = item
card.value=[]
data_search()
}
// 清空搜索历史
function del(){
wx.showModal({
title:'提示',
content:'确定要删除吗?',
success:function(sm){
if(sm.confirm){
wx.removeStorageSync('search_key')
history.value=[]
}else if(sm.cancel){
console.log('用户取消')
}
}
})
}
上面代码应该没什么需要讲解的,比较简单,若不明白的可以留言,看到就会回。