在微信小程序中实现搜索功能是提升用户体验的重要方式。下面我将详细介绍如何在小程序中实现一个完整的搜索功能。

1. 页面布局 (WXML)

编写search.wxml页面布局文件

<!-- pages/search/search.wxml -->
<view class="search-container">
  <navigation-bar title="搜索" back="{{true}}" color="#000000" background="#ffffff" />
  <!-- 搜索区域 -->
  <view class="search-top-container">
    <input type="text" placeholder="🔍 商品搜索" class="et-search" bindinput="searchInput" />
    <text class="btn-search" bind:tap="onClickSearchHandle">搜索</text>
  </view>
  <!-- 搜索内容展示区域 -->
  <scroll-view scroll-y class="scrollarea">
    <view class="grid-container">
      <view class="grid-item " wx:for="{{productList}}" wx:key="product_id" bind:tap="onClickItem" data-item="{{item}}">
        <image src="{{item.product_img}}" mode="aspectFill" />
        <text class="product-name">{{item.product_title}}</text>
        <view class="product-price-view">
          <span style="color:#f3514f; font-size: 22rpx">¥</span>
          <text class="product-price">{{item.product_price}}</text>
        </view>
      </view>
    </view>
  </scroll-view>
</view>
  • 这里默认使用微信自带的navigation-bar,所以还需要在search.json文件中注册
  • 这里需要使用到scroll-view组件,因为当搜索到的内容超过手机一屏时,页面就需要上下滑动来查看所有搜索到的内容区域
{
  "usingComponents": {
    "navigation-bar": "/components/navigation-bar/navigation-bar"
  }
}

2. 样式设计 (WXSS)

编写search.wxss样式文件

/* pages/search/search.wxss */

.search-container {
	display: flex;
	height: 100vh;
	flex-direction: column;
}

.scrollarea{
	flex: 1;
	overflow: scroll;
}

.search-top-container {
	display: flex;
	margin-left: 20rpx;
	margin-right: 20rpx;
	display: flex;
	height: 70rpx;
	background-color: #f5f5f5;
	align-items: center;
	justify-content: space-between;
	padding-left: 10rpx;
	padding-right: 20rpx;
}

.search-top-container .btn-search {
	background-color: #f3514f;
	color: #ffffff;
	font-size: 22rpx;
	width: 100rpx;
	height: 50rpx;
	line-height: 50rpx;
	text-align: center;
	border-radius: 10rpx;
}

.search-top-container .et-search {
	width: 100%;
	margin-right: 20rpx;
	font-size: 24rpx;
}

.grid-container {
  display: flex;
  flex-wrap: wrap;
  /* flex-wrap: wrap 一行显示不下,自动换行 */
  margin: 16rpx;
  justify-content: space-between;
  /* space-between 元素两端对齐,剩余空间元素间隔都相等 */
}

.grid-item {
  display: flex;
  width: 49%;
  flex-direction: column;
  box-sizing: border-box;
  margin-top: 16rpx;
}

.grid-item>image {
  width: 100%;
  border-radius: 10rpx 10rpx 0 0;
}

.grid-item text {
  margin-top: 6rpx;
}

.product-price {
  font-size: 26rpx;
  color: #f3514f;
  font-weight: 600;
}

.product-name {
	display: inline-block;
  white-space: nowrap;
  text-overflow: ellipsis;
  margin-top: 8rpx;
  overflow: hidden;
}

3. 逻辑实现 (JS)

在search.js中具体实现代码逻辑

  1. 动态获取搜索框中的内容,给搜索框绑定事件bindinput="searchInput"
  /**
   * 获取搜索框内容
   */
  searchInput(options) {
    this.setData({
      keyword: options.detail.value
    })
  },
  1. 点击搜索按钮获取输入框中的内容
/**
   * 搜索
   */
  onClickSearchHandle() {
    if (this.data.keyword === '') {
      wx.showToast({
        title: '搜索内容不能为空~',
        icon: 'error'
      })
      return
    }
    const prams = {
      keyword: this.data.keyword
    }
    http.get('/search', prams).then(res => {
      if (res.data.code == 200) {
         if(res.data.data.list.length>0){
          this.setData({
            productList: res.data.data.list
          })
         }else{
           wx.showToast({
             title: '神马数据都没有~',
             icon: 'error'
           })
         }
       
      }
    })
  },

上面代码还是比较好理解,就做了两件事:

  • 首先判断搜索框的内容不能为空
  • 然后调用api接口,获取返回的数据

注意事项: http.get(‘/search’)是通过调用接口api获取自己后台接口数据,这里不具体讲后台接口的实现

  1. 列表点击事件

给组件绑定点击事件bind:tap="onClickItem"

  /**
   * 列表点击事件
   */
  onClickItem(options){
    let itemInfo = options.currentTarget.dataset.item
    wx.navigateTo({
      url: '/pages/details/details?item=' + JSON.stringify(itemInfo),
    })
  },

  1. 具体search.js代码实现过程
// pages/search/search.js
import http from '../../net/http'
Page({

  /**
   * 页面的初始数据
   */
  data: {
    keyword: '', //检索搜素框中的文本
    productList: [] //搜索返回的数据
  },


  /**
   * 获取搜索框内容
   */
  searchInput(options) {
    this.setData({
      keyword: options.detail.value
    })
  },


  /**
   * 列表点击事件
   */
  onClickItem(options){
    let itemInfo = options.currentTarget.dataset.item
    wx.navigateTo({
      url: '/pages/details/details?item=' + JSON.stringify(itemInfo),
    })
  },


  /**
   * 搜索
   */
  onClickSearchHandle() {
    if (this.data.keyword === '') {
      wx.showToast({
        title: '搜索内容不能为空~',
        icon: 'error'
      })
      return
    }
    const prams = {
      keyword: this.data.keyword
    }
    http.get('/search', prams).then(res => {
      if (res.data.code == 200) {
         if(res.data.data.list.length>0){
          this.setData({
            productList: res.data.data.list
          })
         }else{
           wx.showToast({
             title: '神马数据都没有~',
             icon: 'error'
           })
         }
       
      }
    })
  },
})

4. 效果图

在这里插入图片描述

更多推荐