小程序中封装下拉选择框

小程序中没有现成的下拉选择组件,有个picker组件,但是是底部弹出的,不满足我的需求,所以重新封装了一个。

封装的下拉组件

html部分:

html 复制代码
<view class="select_all_view">
  <!-- 内容说明,可以没有 -->
  <view class="select_title" wx:if="{{title}}">{{title}}</view>
  <view class="select_view" style="width: {{selectWidth}};">
    <!-- 输入框 -->
    <view class="inputPlaceholder" bindtap="startChange">
      <text class="text" wx:if='{{select}}'>{{select}}</text>
      <text class="text placeholder_text" wx:else="{{select}}">{{placeholder}}</text>
      <view class="drop_down" wx:if='{{changable}}'>
        <image style="width:48rpx;height:48rpx" src="../../image/drop_up.png" mode="" />
      </view>
      <view class="drop_down" wx:else='{{changable}}'>
        <image style="width:48rpx;height:48rpx" src="../../image/drop_down2.png" mode="" />
      </view>
    </view>
    <!-- 下拉展开后的可选择内容 -->
    <view class="content" wx:if='{{changable}}'>
      <view class="select_item {{item.id==selectId ? 'active':''}}" wx:for="{{selectcontent}}" wx:key="idnex" bindtap="changecontent" data-datavalue="{{item}}">
        {{item.name}}
      </view>
    </view>
  </view>
</view>

css部分:

css 复制代码
.select_all_view {
  display: flex;
  z-index: 999;
}

.select_view {
  display: inline;
  position: relative;
}

.inputPlaceholder {
  width: 100%;
  height: 64rpx;
  border: 2rpx solid #3A3A3A;
  font-size: 28rpx;
  line-height: 32rpx;
  color: #D8D4D4;
  border-radius: 12rpx;
  padding-left: 30rpx;
  box-sizing: border-box;
  position: relative;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.select_view .inputPlaceholder .text {
  line-height:64rpx;
}

.placeholder_text {
  color: #9B9B9B;
  font-size: 28rpx;
}

.drop_down {
  position: absolute;
  right: 12rpx;
  top: 8rpx;
}

.content {
  width: 100%;
  background: #FFFFFF;
  color: #505050;
  font-size: 30rpx;
  box-shadow: 0 0 12rpx 2rpx rgba(0, 0, 0, 0.38);
  border-radius: 16rpx;
  padding: 10rpx 12rpx;
  box-sizing: border-box;
  position: absolute;
  top: 76rpx;
  z-index: 999;
}

.select_item {
  width: 100%;
  height: 76rpx;
  display: flex;
  justify-content: center;
  align-items: center;
}

.select_view .content .active {
  background: #EDF5FF;
  border-radius: 4rpx;
  color: #1061FE;
}

js部分:

javascript 复制代码
Component({
  properties: {
    selectWidth: {
      type: String,
      value: '100%'
    },
    title: {
      type: String,
      value: ""
    },
    nameList: {
      type: Array,
      value: [],
      observer: function () {
        //有的时候选项组是后端获取数据来的,初始化时可能为[],所以这里使用obersver,当父组件中值改变时触发
        this.processData();
      }
    },
    nowId: {
      type: Number,
      value: -1
    },
    nowName: {
      type: String,
      value: "",
      observer: function () {
        this.setData({
          select: this.properties.nowName,
          selectId: this.properties.nowId,
        });
      }
    },
    placeholder: {
      type: String,
      value: ""
    }
  },

  /**
   * 页面的初始数据
   */
  data: {
    selectcontent: [],
    changable: false, //箭头切换
    select: undefined, //选中的值
    selectId: undefined, //选中的id
  },
  methods: {
    // 下拉框收起和展开
    startChange(e) {
      this.setData({
        changable: !this.data.changable
      })
    },
    // 选择数据后回显
    changecontent(e) {
      this.setData({
        select: e.currentTarget.dataset.datavalue.name,
        selectId: e.currentTarget.dataset.datavalue.id,
        changable: false
      })
      this.triggerEvent("handleChange", { item: e.currentTarget.dataset.datavalue });//向父组件传参
    },
    //处理数据,复制一遍,因为子组件不能直接改变父组件的传进来的值。
    processData() {
      this.setData({
        selectcontent: this.properties.nameList,
        select: this.properties.nowName,
        selectId: this.properties.nowId,
      });
    },
    // 关闭下拉框
    closeSelect() {
      this.setData({
        changable: false
      });
    }
  }
})

在父组件中使用:

HTML部分:

html 复制代码
<view class="dropdown_box">
  <dropdown style="margin-right: 20rpx;" class="dropdown" id="dropdown1" selectWidth="240rpx" nowId="{{firstTitleId}}" nameList="{{firstTitle}}" placeholder="请选择" nowName="{{firstTitleVal}}" bind:handleChange="changeFirstTitle"></dropdown>
  <dropdown class="dropdown" id="dropdown2" selectWidth="240rpx" nowId="{{secondTitleId}}" nameList="{{secondTitle}}" nowName="{{secondTitleVal}}" placeholder="请选择" bind:handleChange="changeSecondTitle"></dropdown>
  <dropdown class="dropdown" id="dropdown3" nowId="{{wordLimitId}}" nameList="{{wordLimitList}}" nowName="{{wordLimitVal}}" placeholder="请选择字数" bind:handleChange="changeWords"></dropdown>
</view>

.json文件:

javascript 复制代码
{
  "usingComponents": {
    "dropdown":"../component/dropdown/dropdown"
  }
}

js部分:

javascript 复制代码
Page({

  /**
   * 页面的初始数据
   */
  data: {
    firstTitle: [
      {
        id: 1,
        name: '标题创作'
      },
      {
        id: 2,
        name: '社媒文案'
      },
      {
        id: 3,
        name: '故事创作'
      },
    ],
    secondTitle: [],  //二级标题数组
    wordLimitList: [
      {
        id: 1,
        name: '不限',
        value: 800
      },
      {
        id: 2,
        name: '约150字≈30s',
        value: 150
      },
      {
        id: 3,
        name: '约300字≈60s',
        value: 300
      },
      {
        id: 4,
        name: '约600字≈120s',
        value: 600
      },
    ],
    firstTitleVal: "社媒文案",
    firstTitleId: 2,
    secondTitleVal: "文章改写",
    secondTitleId: 4,
    wordLimitVal: "",
    wordLimitId: 1
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
  },
  // 选择一级标题
  changeFirstTitle(e) {
    let selectId = e.detail.item.id
  },
  // 选择二级标题
  changeSecondTitle(e) {
    console.log(e)
  },
  // 选择字数
  changeWords(e) {
  },
  //点击当前选择框时,关闭其他下拉弹出框;点击页面其他部分,关闭所有下拉弹出框
  handlePageTap(e) {
    const dropdownIds = ['dropdown1', 'dropdown2', 'dropdown3'];
    const clickedId = e.target.id;
    if (dropdownIds.includes(clickedId)) {
      const otherDropdownIds = dropdownIds.filter(id => id !== clickedId);
      otherDropdownIds.forEach(id => {
        const dropdown = this.selectComponent('#' + id);
        dropdown.closeSelect();
      });
    } else {
      const dropdowns = this.selectAllComponents('.dropdown');
      dropdowns.forEach(dropdown => {
        dropdown.closeSelect();
      });
    }
  },
})

页面效果图:

相关推荐
Martin -Tang26 分钟前
vite和webpack的区别
前端·webpack·node.js·vite
迷途小码农零零发27 分钟前
解锁微前端的优秀库
前端
王解1 小时前
webpack loader全解析,从入门到精通(10)
前端·webpack·node.js
我不当帕鲁谁当帕鲁1 小时前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段
前端·javascript·arcgis
qq_332783541 小时前
wx小程序turf.js判断点是否位于该多边形内部
小程序
那一抹阳光多灿烂1 小时前
工程化实战内功修炼测试题
前端·javascript
放逐者-保持本心,方可放逐2 小时前
微信小程序=》基础=》常见问题=》性能总结
前端·微信小程序·小程序·前端框架
计算机-秋大田2 小时前
基于微信小程序的养老院管理系统的设计与实现,LW+源码+讲解
java·spring boot·微信小程序·小程序·vue
毋若成4 小时前
前端三大组件之CSS,三大选择器,游戏网页仿写
前端·css
红中马喽4 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习