翼度科技»论坛 编程开发 JavaScript 查看内容

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

8

主题

8

帖子

24

积分

新手上路

Rank: 1

积分
24
1.首先在components 里面设置组件名称:van-select(随便取名字);
2.新建文件写代码:
wxml:
  1. <view class="w100 select_all_view">
  2.   <!-- 标题,可以没有 -->
  3.   <view class="mr-10 pt-10 size-28" style="width: {{titleWidth}};" wx:if="{{title}}">{{title}}</view>
  4.   <view class="select_view relative" style="width: {{title ? 'calc(100% - ' + titleWidth + ' - 10rpx)' : '100%'}};max-width: {{title ? 'calc(100% - ' + titleWidth + ' - 10rpx)' : '100%'}};">
  5.     <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;">
  6.       <block wx:if="{{disabled || readonly}}">
  7.         <view class="flex-1" wx:if="{{selectLabel}}">{{selectLabel}}</view>
  8.         <view class="flex-1 gray-3 line-1" wx:else>{{placeholder}}</view>
  9.         <van-icon class="gray-3" name="arrow-down" />
  10.       </block>
  11.       <block wx:else>
  12.         <block wx:if="{{selectLabel}}">
  13.           <view class="flex-1">{{selectLabel}}</view>
  14.           <van-icon class="gray-3" name="clear" wx:if='{{!show}}' catchtap="clearInput" />
  15.           <van-icon class="gray-3" name="arrow-up" wx:else />
  16.         </block>
  17.         <block wx:else>
  18.           <view class="flex-1 gray-3 line-1">{{placeholder}}</view>
  19.           <van-icon class="gray-3" name="arrow-down" class="transfer {{show ? 'is-reverse' : 'no-reverse' }}" />
  20.         </block>
  21.       </block>
  22.     </view>
  23.     <!-- 下拉展开后的可选择内容 -->
  24.     <block wx:if='{{show}}'>
  25.       <view class="{{toTop ? 'triangleBox-top' : 'triangleBox'}}">
  26.         <view class="{{toTop ? 'triangle-top' : 'triangle'}}"></view>
  27.       </view>
  28.       <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;'}}">
  29.         <view class="pd-10 center gray-3" wx:if="{{options.length < 1}}">暂无数据</view>
  30.         <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:''}};">
  31.           {{item[labelName]}}
  32.         </view>
  33.       </view>
  34.     </block>
  35.   </view>
  36. </view>
复制代码
wxss:
  1. .select_all_view {
  2.   display: flex;
  3.   justify-content: start;
  4.   align-items: start;
  5.   z-index: 999;
  6.   margin-bottom: 20rpx;
  7. }

  8. .select_view {
  9.   /* min-width: 200rpx; */
  10.   min-height: 64rpx;
  11. }

  12. .inputPlaceholder {
  13.   font-size: 28rpx;
  14. }
  15. .flex_l{
  16.   display: flex;
  17. }
  18. .flex-1{
  19.   flex: 1;
  20. }
  21. .pd-10{
  22.   padding:20rpx;
  23. }
  24. .relative{
  25.   position: relative;
  26. }
  27. .radius-10{
  28.   border-radius: 10rpx;
  29. }
  30. .icon {
  31.   position: absolute;
  32.   right: 12rpx;
  33.   top: 20rpx;
  34. }

  35. .contentItem {
  36.   height: 30rpx;
  37.   line-height: 30rpx;
  38.   font-size: 24rpx;
  39. }

  40. .content {
  41.   width: calc(100% - 4px);
  42.   margin-left: 2px;
  43.   position: absolute;
  44.   z-index: 999;
  45.   max-height: 150rpx;
  46.   background: #FFFFFF;
  47.   /* border: 1px solid #ccc; */
  48.   box-shadow: 0 0 4px #ccc;
  49.   opacity: 1;
  50.   /* margin-top: 10rpx; */
  51.   overflow-x: hidden;
  52.   overflow-y: scroll;
  53. }

  54. .triangleBox {
  55.   position: absolute;
  56.   z-index: 1000;
  57.   left: 30rpx;
  58. }

  59. .triangle {
  60.   position: relative;
  61.   border-left: 12rpx solid transparent;
  62.   border-right: 12rpx solid transparent;
  63.   border-bottom: 10rpx solid #ccc;
  64. }

  65. .triangle::after {
  66.   content: '';
  67.   position: absolute;
  68.   top: 3rpx;
  69.   left: -12rpx;
  70.   border-left: 12rpx solid transparent;
  71.   border-right: 12rpx solid transparent;
  72.   border-bottom: 10rpx solid #fff;
  73. }

  74. .triangleBox-top {
  75.   position: absolute;
  76.   z-index: 1000;
  77.   left: 30rpx;
  78.   /* display: none; */
  79. }

  80. .triangle-top {
  81.   position: relative;
  82.   border-left: 12rpx solid transparent;
  83.   border-right: 12rpx solid transparent;
  84.   border-top: 10rpx solid #ccc;
  85. }

  86. .triangle-top::after {
  87.   content: '';
  88.   position: absolute;
  89.   bottom: 3rpx;
  90.   left: -12rpx;
  91.   border-left: 12rpx solid transparent;
  92.   border-right: 12rpx solid transparent;
  93.   border-top: 10rpx solid #fff;
  94. }

  95. .is-reverse {
  96.   transform: rotate(180deg);
  97. }

  98. .transfer {
  99.   transition: transform .3s;
  100. }

  101. .no-reverse {
  102.   transition: rotate(0deg);
  103. }
复制代码
js:
  1. Component({
  2.   options: {
  3.     addGlobalClass: true,
  4.   },
  5.   properties: {
  6.     /* --------- 样式参数 --------- */
  7.     titleWidth: { // 标题长度
  8.       type: String,
  9.       value: "60px"
  10.     },
  11.     bgColor: { // 输入框背景颜色
  12.       type: String,
  13.       value: "#fff"
  14.     },
  15.     itemBgColor: { // 选中的选项背景颜色
  16.       type: String,
  17.       value: "#F5F8FE"
  18.     },
  19.     textColor: { // 选中的字体颜色
  20.       type: String,
  21.       value: "#FF5733"
  22.     },
  23.     /* --------- 数据参数 --------- */
  24.     title: { // 下拉框标题
  25.       type: String,
  26.       value: ""
  27.     },
  28.     number: { // 下拉框标题
  29.       type: String,
  30.       value: ""
  31.     },
  32.     options: { // 选项数组
  33.       type: Array,
  34.       value: [],
  35.     },
  36.     labelName: { // 选项数组-绑定的label名称
  37.       type: String,
  38.       value: "dictLabel",
  39.     },
  40.     valueName: { // 选项数组-绑定的value名称
  41.       type: String,
  42.       value: "dictValue"
  43.     },
  44.     modelValue: { // 绑定的value
  45.       type: String,
  46.       value: "",
  47.       observer: function () {
  48.         //如果有默认值,需要匹配出name,所以这里使用obersver,当父组件中值改变时触发
  49.         this.handleData();
  50.       }
  51.     },
  52.     placeholder: { // 输入框为空时占位符
  53.       type: String,
  54.       value: "请选择"
  55.     },
  56.     disabled: { // 是否禁用
  57.       type: Boolean,
  58.       value: false
  59.     },
  60.     readonly: { // 是否只读
  61.       type: Boolean,
  62.       value: false
  63.     }
  64.   },
  65.   /**
  66.    * 页面的初始数据
  67.    */
  68.   data: {
  69.     show: false, //选项框及图标展示
  70.     selectValue: "", //选中的value
  71.     selectLabel: "", //选中的label
  72.     toTop: false, // 下拉框是否展示在输入框上方
  73.   },
  74.   attached() {
  75.     this.handleData()
  76.   },
  77.   methods: {
  78.     // 清空输入框
  79.     clearInput() {
  80.       this.setData({
  81.         selectValue: "", //选中的value
  82.         selectLabel: "", //选中的label
  83.         show: false,
  84.       })
  85.     },
  86.     // 下拉框收起和展开
  87.     changeShow(e) {
  88.       let that = this
  89.       const query = wx.createSelectorQuery();
  90.       // 选择当前点击的 view 元素
  91.       query.select('.inputPlaceholder'+this.data.number).boundingClientRect();
  92.       query.exec(function (res) { // res[0].bottom 是元素距离可视区域顶部的距离加上元素自身的高度; res[1].scrollTop 是页面的滚动距离
  93.         var show = !that.data.show
  94.         if (res[0]) {
  95.           /* that.triggerEvent("handleShow", show); // [暂未发现]处理滚动选项区域时背景页面滚动问题 */
  96.           let toBottom = wx.getSystemInfoSync().windowHeight - res[0].bottom;
  97.           console.log('距离设备底部的距离:', toBottom);
  98.           that.setData({
  99.             toTop: toBottom < 150 ? true : false,
  100.             show: show
  101.           })
  102.         } else {
  103.           that.setData({ show: show })
  104.         }
  105.       });
  106.     },
  107.     // 选择数据后回显
  108.     handleChange(e) {
  109.       let { item } = e.currentTarget.dataset
  110.       let { labelName, valueName } = this.data
  111.       this.setData({
  112.         selectValue: item[valueName],
  113.         selectLabel: item[labelName],
  114.         show: false
  115.       })
  116.       let obj = {}
  117.       obj[valueName] = item[valueName]
  118.       obj[labelName] = item[labelName]
  119.       this.triggerEvent("handleChange", obj);// 传参
  120.     },
  121.     // 匹配值并回显
  122.     handleData() {
  123.       let { modelValue, options, valueName, labelName } = this.properties;
  124.       if (modelValue) {
  125.         let item = options.find(r => r[valueName] == modelValue)
  126.         this.setData({
  127.           selectLabel: item ? item[labelName] : modelValue,
  128.           selectValue: modelValue,
  129.         });
  130.       }
  131.     }
  132.   }
  133. })
复制代码
json:
  1. {
  2.   "component": true,
  3.   "usingComponents": {}
  4. }
复制代码
  1. 以上就是组件的全部代码,当然你也可以自己再按照需求改造,接下来就是组件的应用:
复制代码
组件应用:
1.在所需要用组件的页面中引入组件,在所需页面的json中:
  1. {
  2.   "navigationBarTitleText": "",
  3.   "usingComponents": {
  4.       "wan-select": "../components/van-select/index"
  5.   }
  6. }
复制代码
2.在wxml里面使用:
  1. <view class="cont-box">
  2.    <wan-select
  3. class="inputPlaceholder1"
  4. options="{{options1}}"
  5. number="1"
  6. labelName="text"
  7. valueName="id"
  8. modelValue="{{selectedId1}}"
  9. placeholder="请选择"
  10. bindhandleChange="handleChange"
  11. title=""
  12. readonly="{{false}}"
  13. disabled="{{options1.length == 0}}"></wan-select>
  14. </view>
复制代码
说明:

  • class="inputPlaceholder1" (自己写的类,可以修改样式)
  • options="{{options1}}"(下拉框的选项数据)
  • labelName="text"(选项数组-绑定的label名称)
  • valueName="id"(选项数组-绑定的value名称)
  • number="1"(自定义的值,多个select 有关联的情况下,添加,根据自己需求,一个的话没必要)
  • modelValue="{{selectedId1}}"(为了回显下拉框数据中选中的项)
  • bindhandleChange="handleChange"(操作事件)
  • title="" (下拉框左侧添加名称)
  • readonly="{{false}}"(是否只读)
  • disabled="“(是否禁用)
如图所示:

总结
到此这篇关于原生微信小程序中封装一个模拟select下拉框组件的文章就介绍到这了,更多相关微信小程序封装模拟select下拉框组件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

来源:https://www.jb51.net/javascript/331120ocr.htm
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具