【自定义微信小程序拉下选择过滤组件】searchable-select

【自定义微信小程序拉下选择过滤组件】searchable-select

组件说明

点击输入框获取焦点,输入内容,自动匹配搜索结果,点击搜索结果,自动填充搜索结果。

组件使用

  1. 将组件文件夹放在项目中。
  2. 在需要使用的页面的json文件中,添加组件的路径。
json 复制代码
{
  "usingComponents": {
    "searchable-select": "/components/searchable-select/searchable-select"
  }
}
  1. 在需要使用的页面的wxml文件中,使用组件。
html 复制代码
<searchable-select options="{{ hospitalOptions }}" selectedValue="{{ selectedValue }}" placeholder="搜索医院" bind:select="onSelect"></searchable-select>
  1. 在需要使用的页面的js文件中,定义组件的属性和方法。
js 复制代码
Page({
  data: {
    hospitalOptions: [
      { id: 1, name: '选项1' },
      { id: 2, name: '选项2' },
      { id: 3, name: '选项3' }
    ], 
    selectedValue: '' 
  },
  methods: {
    // 下拉选择医院
    onSelect(e) {
      const selectedValue = e.detail.value;
      this.setData({
        selectedValue: selectedValue.label,
        hospitalCurrent: selectedValue.value
      });
    },
  }
})

组件详情

searchable-select.js

js 复制代码
Component({
  properties: {
    // 下拉选项列表
    options: {
      type: Array,
      value: []
    },
    // 初始选中的值
    selectedValue: {
      type: String,
      value: ''
    },
    // 输入框的占位符
    placeholder: {
      type: String,
      value: '请选择'
    }
  },
  data: {
    isOpen: false, // 下拉框是否展开
    filteredOptions: [], // 过滤后的选项列表
    inputValue: '', // 输入框的值
    showNoData: false // 是否显示暂无数据提示
  },
  observers: {
    // 监听 options 属性变化,更新过滤后的选项列表
    options(newOptions) {
      this.setData({
        filteredOptions: newOptions
      });
    },
    selectedValue(newValue) {
      this.setData({
        inputValue: newValue
      });
    }
  },
  methods: {
    // 输入框获得焦点时展开下拉框
    onInputFocus() {
      this.setData({
        isOpen: true
      });
      this.filterOptions(this.data.inputValue);
    },
    // 防抖函数
    debounce(func, delay) {
      let timer = null;
      return function () {
        const context = this;
        const args = arguments;
        clearTimeout(timer);
        timer = setTimeout(() => {
          func.apply(context, args);
        }, delay);
      };
    },
    // 处理输入框输入事件
    handleInput: function (e) {
      const inputValue = e.detail.value;
      this.debounceFilterOptions(inputValue);
    },
    // 过滤选项列表
    filterOptions(inputValue) {
      if (!inputValue) {
        this.setData({
          filteredOptions: [],
          showNoData: true
        });
        return;
      }

      const filteredOptions = this.data.options.filter(option => {
        return option.label.includes(inputValue);
      });
      const showNoData = filteredOptions.length === 0;

      this.setData({
        inputValue,
        filteredOptions,
        showNoData
      });
    },
    // 防抖处理过滤选项
    debounceFilterOptions: function () {
      this.debounce(this.filterOptions, 500).apply(this, arguments);
    },
    handleSelectOpen() {
      this.setData({
        isOpen: false
      });
    },
    // 处理选项点击事件
    handleOptionClick(e) {
      const selectedValue = e.currentTarget.dataset.value;
      this.setData({
        inputValue: selectedValue.label,
        isOpen: false,
        showNoData: false
      });
      // 触发自定义事件,通知父组件选中的值
      this.triggerEvent('select', { value: selectedValue });
    }
  }
});

searchable-select.json

json 复制代码
{
  "component": true,
  "usingComponents": {},
  "styleIsolation": "isolated"
}

searchable-select.wxml

html 复制代码
<view class="searchable-select">
  <view class="input-container">
    <input
      class="plugin-input"
      type="text"
      value="{{ inputValue }}"
      placeholder="{{ placeholder }}"
      bindfocus="onInputFocus"
      bindblur="onInputBlur"
      bindinput="handleInput"
      readonly="{{ !isOpen }}"
    />
    <view class="icon-wrapper {{ isOpen ? 'open' : '' }}"></view>
  </view>
  <view class="dropdown-box" bindtap="handleSelectOpen" wx:if="{{ isOpen }}">
    <view class="dropdown" >
      <view
        class="option {{ inputValue == item.label ? 'selected' : '' }}"
        wx:for="{{ filteredOptions }}"
        wx:key="*this"
        data-value="{{ item }}"
        catchtap="handleOptionClick"
      >
        {{ item && item.label }}
      </view>
      <view class="no-data" wx:if="{{ showNoData }}">暂无</view>
    </view>
  </view>
</view>

searchable-select.wxss

css 复制代码
/* 修改为直接类名选择器 */
.plugin-input {
  flex: 1;
  border: none;
  outline: none;
  z-index: 99;
}

.searchable-select {
  position: relative;
}

.input-container {
  display: flex;
  align-items: center;
  border-bottom: 1rpx solid #f1f1f1;
  padding: 20rpx 28rpx;
}

.dropdown-box {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  min-height: 100vh;
  z-index: 10;
}

.dropdown {
  top: 100%;
  left: 0;
  right: 0;
  box-sizing: border-box;
  border-top: none;
  max-height: 300px;
  overflow-y: auto;
  z-index: 10;
  border-radius: 6rpx;
  padding: 12rpx 20rpx 10rpx 20rpx;
  box-shadow: 0rpx 0rpx 1rpx 1rpx rgba(0, 0, 0, 0.2) inset;
  background-color: #fff;
  margin: 0 28rpx;
}

.option {
  padding: 20rpx 10rpx;
  cursor: pointer;
  border-bottom: 1rpx solid #eee;
}

.option .selected {
  background-color: #f0f0f0;
}

.option:last-child {
  border-bottom: none;
}

.option:hover {
  background-color: #f0f0f0;
}

.no-data {
  padding: 10px;
  text-align: center;
  color: #999;
}

.icon-wrapper::after {
  content: '';
  position: absolute;
  top: 50%;
  right: 28rpx;
  transform: translateY(-50%);
  width: 0;
  height: 0;
  border: 10rpx solid transparent;
  border-top: 10rpx solid #999;
  transition: transform 0.3s ease;
}

.icon-wrapper.open::after {
  transform: translateY(-50%) rotate(180deg);
  -webkit-transform: translateY(-50%) rotate(180deg);
  -moz-transform: translateY(-50%) rotate(180deg);
  -ms-transform: translateY(-50%) rotate(180deg);
  -o-transform: translateY(-50%) rotate(180deg);
}

效果图:

相关推荐
老虎06279 小时前
JavaWeb(苍穹外卖)--学习笔记13(微信小程序开发,缓存菜品,Spring Cache)
笔记·学习·微信小程序
郭邯14 小时前
小程序中自定义组件的样式隔离
微信小程序
每天开心16 小时前
噜噜旅游App(4)——构建旅游智能客服模块,实现AI聊天
前端·微信小程序·前端框架
老华带你飞1 天前
口腔助手|口腔挂号预约小程序|基于微信小程序的口腔门诊预约系统的设计与实现(源码+数据库+文档)
java·数据库·微信小程序·小程序·论文·毕设·口腔小程序
尸僵打怪兽1 天前
HBuilder X打包发布微信小程序
微信小程序·小程序·打包·hbuilder x
半生过往1 天前
微信小程序文件下载与预览功能实现详解
微信小程序·小程序·notepad++·压缩包下载解压
源码_V_saaskw1 天前
JAVA图文短视频交友+自营商城系统源码支持小程序+Android+IOS+H5
java·微信小程序·小程序·uni-app·音视频·交友
996幸存者2 天前
uni-app区域选择、支持静态、动态数据
微信小程序·uni-app
ᥬ 小月亮2 天前
Uniapp编写微信小程序,绘制动态圆环进度条
微信小程序·小程序·uni-app
The_era_achievs_hero2 天前
UniappDay03
vue.js·微信小程序·uni-app