当前位置: 首页 > news >正文

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

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

组件说明

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

组件使用

  1. 将组件文件夹放在项目中。
  2. 在需要使用的页面的json文件中,添加组件的路径。
{"usingComponents": {"searchable-select": "/components/searchable-select/searchable-select"}
}
  1. 在需要使用的页面的wxml文件中,使用组件。
<searchable-select options="{{ hospitalOptions }}" selectedValue="{{ selectedValue }}" placeholder="搜索医院" bind:select="onSelect"></searchable-select>
  1. 在需要使用的页面的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

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

{"component": true,"usingComponents": {},"styleIsolation": "isolated"
}

searchable-select.wxml

<view class="searchable-select"><view class="input-container"><inputclass="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" ><viewclass="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

/* 修改为直接类名选择器 */
.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);
}

效果图:

在这里插入图片描述


http://www.mrgr.cn/news/94849.html

相关文章:

  • VSTO(C#)Excel开发12:多线程的诡异
  • Android的消息机制
  • 用户登出、修改密码或重置密码后,token的删除(flask)
  • LeRobot源码剖析——对机器人各个动作策略的统一封装:包含ALOHA ACT、Diffusion Policy、VLA模型π0
  • 数据结构------线性表(链表)
  • Flask+Vue-Router+JWT实现登录验证
  • 项目实战系列:基于瑞萨RA6M5构建多节点OTA升级-系统设计<一>
  • 【WRF数据准备】 基于CDO/Python 拼接 grib 数据:如ERA5 气象数据
  • 设计模式之外观模式:原理、实现与应用
  • HarmonyOS三层架构实战
  • 【Linux内核系列】:进程板块与文件板块的综合
  • C# 一文读懂委托与事件
  • 【C++进阶一】STL和string
  • Python集合
  • 【MySQL基础-9】深入理解MySQL中的聚合函数
  • SpringCloud 学习笔记2(Nacos)
  • 数据结构篇——二叉树的存储与遍历
  • GaussDB备份数据常用命令
  • SSM框架——Spring面试题
  • 汇编基础知识