Skip to content
本页目录

6. 搜索

6.1 实现搜索页面基础结构

基础结构

vue
<!-- 头部搜索栏 -->
<view class="header">
    <view class="header-search">
        <icon type="search" size="13"></icon>
        <input type="text" class="search-title" v-model="query.keyword" />
    </view>
    <view class="search-btn" @click="getSearch">搜索</view>
</view>
<!-- tabs栏 -->
<van-tabs type="card" color="#1baeae" @click="changeTab" >
    <van-tab title="推荐" name=""></van-tab>
    <van-tab title="新品" name="new"></van-tab>
    <van-tab title="价格" name="price"></van-tab>
</van-tabs>

<!-- 内容列表 -->
<view class="content">
    <!-- 空状态 -->
    <view v-else class="search-tip">
        <image class="empty"  src="https://s.yezgea02.com/1604041313083/kesrtd.png" alt="搜索"></image>
        <view class="finished-text">搜索想要的商品</view>
    </view>
</view>

UI布局样式

scss
.header {
	display: flex;
	justify-content: space-between;
	height: 100rpx;
	line-height: 100rpx;
	padding: 0 30rpx;
	font-size: 30rpx;
	color: #656771;
	.header-search {
		display: flex;
		flex: 1;
		height: 40rpx;
		line-height: 40rpx;
		margin: 20rpx 0;
		padding: 10rpx 0;
		color: #232326;
		background: #f7f7f7;
		border-radius: 40rpx;
		icon {
			padding: 4rpx 18rpx 0 20rpx;
			font-size: 32rpx;
		}
		.search-title {
			font-size: 24rpx;
			color: #666;
			background: #f7f7f7;
			width: 80%;
		}
	}
	.search-btn {
		height: 56rpx;
		margin: 16rpx 0;
		line-height: 56rpx;
		padding: 0 20rpx;
		color: #f7f7f7;
		background-color: $uni-primary;
		border-radius: 10rpx;
		margin-top: 20rpx;
		margin-left: 30rpx;
	}
}

.content {
	height: calc(100vh - 160rpx);
	overflow: hidden;
	.search-tip {
		padding-top: 100rpx;
		.empty {
		  display: block;
		  width: 300rpx;
		  height: 300rpx;
		  margin: 0rpx auto 40rpx;
		}
		.finished-text {
			color: #969799;
			font-size: 28rpx;
			line-height: 28rpx;
			text-align: center;
		}
	}
}

6.2 根据关键词搜索

  1. 查询列表

    • 绑定关键词输入框双向 点击按钮搜索

      js
      // 搜索商品
      const getSearch = () => {
      	init()
      }
      
    • 加载数据 (关键词空不能搜索)

      js
      // 加载数据
      const init = async () => {
      	const { keyword, page, categoryId, orderBy } = state.query
      	console.log(keyword, categoryId);
      	// 0. 判断参数的有效性  关键词 或 类别ID
      	if (!keyword && !categoryId) return state.refreshing = false
      	state.loading = true
      	// 1. 发起请求 keyword不能为空  keyword: '', goodsCategoryId: '', orderBy: '', pageNumber: 1
      	const { data: { totalPage, list } } = await search({ keyword, goodsCategoryId: categoryId, orderBy , pageNumber: page })
      	state.list = state.list.concat(list)
      	state.loading = false
      	// 2. 判断是否还能加载
      	if (page >= totalPage) state.hasMore = false
      	state.refreshing = false
      }
      
  2. 实现列表布局结构

    vue
    <!-- 内容列表 -->
    		<view class="content">
    			<scroll-view scroll-y class="product-list" refresher-enabled :refresher-triggered="refreshing" @refresherrefresh="onRefresh"  @scrolltolower="loadMore">
    				<template v-if="list.length">
    					<view class="product-item" v-for="item in list" :key="item" @click="productDetail(item)">
    						<!-- 左侧内容 -->
    						<image :src="item.goodsCoverImg"></image>
    						<!-- 中间内容 -->
    						<view class="product-info">
    							<view class="name">{{ item.goodsName }}</view>
    							<view class="subtitle">{{ item.goodsIntro }}</view>
    							<text class="price">¥ {{item.sellingPrice}}</text>
    						</view>
    					</view>
    					<!-- 加载状态提示 -->
    					<view class="loading-tip">{{ state.hasMore ? '加载中...' : '没有更多了' }}</view>
    				</template>
    				<view v-else class="search-tip">
    					<image class="empty"  src="https://s.yezgea02.com/1604041313083/kesrtd.png" alt="搜索"></image>
    					<view class="finished-text">搜索想要的商品</view>
    				</view>
    			</scroll-view>
    		</view>
    
  3. 补充UI布局

    scss
    .content {
    	height: calc(100vh - 160rpx);
    	overflow: hidden;
    	.product-list {
    		height: 100%;
    	}
    	
    	.product-item {
    		width: 100%;
    		display: flex;
    		justify-content: space-between;
    		height: 240rpx;
    		padding: 20rpx 0;
    		border-bottom: 2rpx solid #dcdcdc;
    		image {
    			width: 280rpx;
    			height: 240rpx;
    			padding: 0 20rpx;
    			box-sizing: border-box;
    		}
    		.product-info {
    			width: 56%;
    			height: 240rpx;
    			padding: 10rpx;
    			text-align: left;
    			box-sizing: border-box;
    			.name {
    				width: 100%;
    				max-height: 80rpx;
    				line-height: 40rpx;
    				font-size: 30rpx;
    				color: #333;
    				overflow: hidden;
    				text-overflow: ellipsis;
    				white-space: nowrap;
    			}
    			.subtitle {
    				width: 100%;
    				max-height: 40rpx;
    				padding: 20rpx 0;
    				line-height: 50rpx;
    				font-size: 26rpx;
    				color: #999;
    				overflow: hidden;
    			}
    			.price {
    				color: $uni-primary;
    				font-size: 32rpx;
    			}
    		}
    	}
    	
    	.loading-tip {
    		color: #969799;
    		font-size: 24rpx;
    		line-height: 24rpx;
    		text-align: center;
    		padding: 30rpx 0;
    	}
    	
    	.search-tip {
    		padding-top: 100rpx;
    		.empty {
    		  display: block;
    		  width: 300rpx;
    		  height: 300rpx;
    		  margin: 0rpx auto 40rpx;
    		}
    		.finished-text {
    			color: #969799;
    			font-size: 28rpx;
    			line-height: 28rpx;
    			text-align: center;
    		}
    	}
    }
    

6.3 分类ID搜索

  1. 分类页面点击跳转搜索

    js
    // 根据分类选择商品
    const selectProduct = item => {
    	console.log('item', item.categoryId)
    	uni.navigateTo({
    		url: `/subpkg/goods_list/goods_list?categoryId=${item.categoryId}`
    	})
    }
    
  2. onLoad函数中取参数 加载搜索

    js
    onLoad((options) => {
    	// 保存categoryID
    	state.query.categoryId = options.categoryId || ''
    	init()
    })
    

6.4 下拉刷新与上拉加载

  1. scroll-view绑定事件

    vue
    <scroll-view scroll-y class="product-list" refresher-enabled :refresher-triggered="refreshing" @refresherrefresh="onRefresh"  @scrolltolower="loadMore">
    </scroll-view>
    
  2. 实现事件函数

    js
    // 加载更多
    const loadMore = () => {
    	// 1. 判断是否正在加载
    	if (state.loading) return
    	// 2. 判断是否还能加载
    	if (!state.hasMore) return
    	state.query.page += 1
    	init()
    }
    
    // 刷新加载
    const onRefresh = () => {
    	state.refreshing = true
    	state.list = []
    	state.hasMore = true
    	state.query.page = 1
    	init()
    }
    

6.5 排序搜索

  1. tabs绑定事件

  2. 处理事件函数

    js
    // 切换tab类型【排序】
    const changeTab = (e) => {
      console.log('name', e)
      state.query.orderBy = e.detail.name
      onRefresh()
    }
    

6.6 历史搜索

  1. 基础UI布局 使用van-tag排版
  2. 关键词搜索 添加为历史记录
  3. 后置添加 最多10条
  4. 点击历史 进行关键词搜索
  5. 一键删除