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

原生微信小程序中封装一个模拟select 下拉框组件

1.首先在components 里面设置组件名称:van-select(随便取名字);

2.新建文件写代码:

wxml:

<view class="w100 select_all_view"><!-- 标题,可以没有 --><view class="mr-10 pt-10 size-28" style="width: {{titleWidth}};" wx:if="{{title}}">{{title}}</view><view class="select_view relative" style="width: {{title ? 'calc(100% - ' + titleWidth + ' - 10rpx)' : '100%'}};max-width: {{title ? 'calc(100% - ' + titleWidth + ' - 10rpx)' : '100%'}};"><view class="inputPlaceholder h100 w100 radius-10 relative flex_l pd-10 {{ disabled ? 'gray-3' : 'black' }}" bindtap="{{disabled || readonly ? '' : 'changeShow'}}" style="background: {{disabled ?'#f5f7fa' : bgColor}};border: 2rpx solid #ddd;"><block wx:if="{{disabled || readonly}}"><view class="flex-1" wx:if="{{selectLabel}}">{{selectLabel}}</view><view class="flex-1 gray-3 line-1" wx:else>{{placeholder}}</view><van-icon class="gray-3" name="arrow-down" /></block><block wx:else><block wx:if="{{selectLabel}}"><view class="flex-1">{{selectLabel}}</view><van-icon class="gray-3" name="clear" wx:if='{{!show}}' catchtap="clearInput" /><van-icon class="gray-3" name="arrow-up" wx:else /></block><block wx:else><view class="flex-1 gray-3 line-1">{{placeholder}}</view><van-icon class="gray-3" name="arrow-down" class="transfer {{show ? 'is-reverse' : 'no-reverse' }}" /></block></block></view><!-- 下拉展开后的可选择内容 --><block wx:if='{{show}}'><view class="{{toTop ? 'triangleBox-top' : 'triangleBox'}}"><view class="{{toTop ? 'triangle-top' : 'triangle'}}"></view></view><view class="content radius-10 pd-20 size-28" style="{{toTop ? 'top: -' + (options.length > 4 ? 150 : (options.length * 30 + 40)) + 'rpx; margin-top: -6rpx;' : 'margin-top: 10rpx;'}}"><view class="pd-10 center gray-3" wx:if="{{options.length < 1}}">暂无数据</view><view class="line-1 w100 pd-10 contentItem {{item[valueName] == selectValue ? 'bold':''}}" wx:for="{{options}}" wx:key="index" bindtap="handleChange" data-item="{{item}}" style="color: {{ item[valueName] == selectValue ? textColor : '#000'}}; background: {{item[valueName] == selectValue ? itemBgColor:''}};">{{item[labelName]}}</view></view></block></view>
</view>

wxss:

.select_all_view {display: flex;justify-content: start;align-items: start;z-index: 999;margin-bottom: 20rpx;
}.select_view {/* min-width: 200rpx; */min-height: 64rpx;
}.inputPlaceholder {font-size: 28rpx;
}
.flex_l{display: flex;
}
.flex-1{flex: 1;
}
.pd-10{padding:20rpx;
}
.relative{position: relative;
}
.radius-10{border-radius: 10rpx;
}
.icon {position: absolute;right: 12rpx;top: 20rpx;
}.contentItem {height: 30rpx;line-height: 30rpx;font-size: 24rpx;
}.content {width: calc(100% - 4px);margin-left: 2px;position: absolute;z-index: 999;max-height: 150rpx;background: #FFFFFF;/* border: 1px solid #ccc; */box-shadow: 0 0 4px #ccc;opacity: 1;/* margin-top: 10rpx; */overflow-x: hidden;overflow-y: scroll;
}.triangleBox {position: absolute;z-index: 1000;left: 30rpx;
}.triangle {position: relative;border-left: 12rpx solid transparent;border-right: 12rpx solid transparent;border-bottom: 10rpx solid #ccc;
}.triangle::after {content: '';position: absolute;top: 3rpx;left: -12rpx;border-left: 12rpx solid transparent;border-right: 12rpx solid transparent;border-bottom: 10rpx solid #fff;
}.triangleBox-top {position: absolute;z-index: 1000;left: 30rpx;/* display: none; */
}.triangle-top {position: relative;border-left: 12rpx solid transparent;border-right: 12rpx solid transparent;border-top: 10rpx solid #ccc;
}.triangle-top::after {content: '';position: absolute;bottom: 3rpx;left: -12rpx;border-left: 12rpx solid transparent;border-right: 12rpx solid transparent;border-top: 10rpx solid #fff;
}.is-reverse {transform: rotate(180deg);
}.transfer {transition: transform .3s;
}.no-reverse {transition: rotate(0deg);
}

js:

Component({options: {addGlobalClass: true,},properties: {/* --------- 样式参数 --------- */titleWidth: { // 标题长度type: String,value: "60px"},bgColor: { // 输入框背景颜色type: String,value: "#fff"},itemBgColor: { // 选中的选项背景颜色type: String,value: "#F5F8FE"},textColor: { // 选中的字体颜色type: String,value: "#FF5733"},/* --------- 数据参数 --------- */title: { // 下拉框标题type: String,value: ""},number: { // 下拉框标题type: String,value: ""},options: { // 选项数组type: Array,value: [],},labelName: { // 选项数组-绑定的label名称type: String,value: "dictLabel",},valueName: { // 选项数组-绑定的value名称type: String,value: "dictValue"},modelValue: { // 绑定的valuetype: String,value: "",observer: function () {//如果有默认值,需要匹配出name,所以这里使用obersver,当父组件中值改变时触发this.handleData();}},placeholder: { // 输入框为空时占位符type: String,value: "请选择"},disabled: { // 是否禁用type: Boolean,value: false},readonly: { // 是否只读type: Boolean,value: false}},/*** 页面的初始数据*/data: {show: false, //选项框及图标展示selectValue: "", //选中的valueselectLabel: "", //选中的labeltoTop: false, // 下拉框是否展示在输入框上方},attached() {this.handleData()},methods: {// 清空输入框clearInput() {this.setData({selectValue: "", //选中的valueselectLabel: "", //选中的labelshow: false,})},// 下拉框收起和展开changeShow(e) {let that = thisconst query = wx.createSelectorQuery();// 选择当前点击的 view 元素query.select('.inputPlaceholder'+this.data.number).boundingClientRect();query.exec(function (res) { // res[0].bottom 是元素距离可视区域顶部的距离加上元素自身的高度; res[1].scrollTop 是页面的滚动距离var show = !that.data.showif (res[0]) {/* that.triggerEvent("handleShow", show); // [暂未发现]处理滚动选项区域时背景页面滚动问题 */let toBottom = wx.getSystemInfoSync().windowHeight - res[0].bottom;console.log('距离设备底部的距离:', toBottom);that.setData({toTop: toBottom < 150 ? true : false,show: show})} else {that.setData({ show: show })}});},// 选择数据后回显handleChange(e) {let { item } = e.currentTarget.datasetlet { labelName, valueName } = this.datathis.setData({selectValue: item[valueName],selectLabel: item[labelName],show: false})let obj = {}obj[valueName] = item[valueName]obj[labelName] = item[labelName]this.triggerEvent("handleChange", obj);// 传参},// 匹配值并回显handleData() {let { modelValue, options, valueName, labelName } = this.properties;if (modelValue) {let item = options.find(r => r[valueName] == modelValue)this.setData({selectLabel: item ? item[labelName] : modelValue,selectValue: modelValue,});}}}
})

json:

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

以上就是组件的全部代码,当然你也可以自己再按照需求改造,接下来就是组件的应用:

组件应用:

1.在所需要用组件的页面中引入组件,在所需页面的json中:

{"navigationBarTitleText": "","usingComponents": {"wan-select": "../components/van-select/index"}
}

2.在wxml里面使用:

<view class="cont-box"><wan-select 
class="inputPlaceholder1" 
options="{{options1}}" 
number="1" 
labelName="text" 
valueName="id" 
modelValue="{{selectedId1}}" 
placeholder="请选择" 
bindhandleChange="handleChange" 
title="" 
readonly="{{false}}" 
disabled="{{options1.length == 0}}"></wan-select>
</view>

说明:

class="inputPlaceholder1" (自己写的类,可以修改样式)

options="{{options1}}"(下拉框的选项数据)

labelName="text"(选项数组-绑定的label名称)

valueName="id"(选项数组-绑定的value名称)

number="1"(自定义的值,多个select 有关联的情况下,添加,根据自己需求,一个的话没必要)

modelValue="{{selectedId1}}"(为了回显下拉框数据中选中的项)

bindhandleChange="handleChange"(操作事件)

title="" (下拉框左侧添加名称)

readonly="{{false}}"(是否只读)

disabled="“(是否禁用)

如图所示:

http://www.lryc.cn/news/486807.html

相关文章:

  • 商品管理系统引领时尚零售智能化升级 降价商品量锐减30%
  • UE5 5.1.1创建C++项目,显示error C4668和error C4067
  • spring boot 集成 redis 实现缓存的完整的例子
  • json-bigint处理前端精度丢失问题
  • 【算法】【优选算法】前缀和(下)
  • Node.js 23 发布了!
  • 如何通过低代码逻辑编排实现业务流程自动化?
  • thinkphp6模板调用URL方法生成的链接异常
  • Spring Boot汽车资讯:科技驱动的未来
  • 嵌入式硬件电子电路设计(五)LDO低压差线性稳压器全面详解
  • qiankun主应用(vue2+element-ui)子应用(vue3+element-plus)不同版本element框架css样式相互影响的问题
  • resnet50,clip,Faiss+Flask简易图文搜索服务
  • 使用OkHttp进行HTTPS请求的Kotlin实现
  • 使用Mac下载MySQL修改密码
  • 运维面试题.云计算面试题集锦第一套
  • CSS-flex布局
  • Linux:进程的优先级 进程切换
  • web应用安全和信息泄露
  • 创建vue3项目步骤
  • 尽量通俗易懂地概述.Net U nity跨语言/跨平台相关知识
  • 【AlphaFold3】开源本地的安装及使用
  • vue2/vue3中使用的富文本编辑器vue-quill
  • 论文阅读《BEVFormer v2》
  • 自动化运维(k8s):一键获取指定命名空间镜像包脚本
  • HarmonyOS ArkUI(基于ArkTS) 开发布局 (上)
  • 第九部分 :1.STM32之通信接口《精讲》(USART,I2C,SPI,CAN,USB)
  • 5. langgraph中的react agent使用 (从零构建一个react agent)
  • uniapp vue3的下拉刷新和上拉加载
  • STM32设计井下瓦斯检测联网WIFI加Zigbee多路节点协调器传输
  • Vue 3 中的原生事件监听与组件事件处理详解