小程序中封装下拉选择框

小程序中没有现成的下拉选择组件,有个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();
      });
    }
  },
})

页面效果图:

相关推荐
码事漫谈13 分钟前
解决 Anki 启动器下载错误的完整指南
前端
赵庆明老师20 分钟前
Uniapp微信小程序开发:微信小程序支付功能后台代码
微信小程序·小程序·uni-app
im_AMBER33 分钟前
Web 开发 27
前端·javascript·笔记·后端·学习·web
蓝胖子的多啦A梦1 小时前
低版本Chrome导致弹框无法滚动的解决方案
前端·css·html·chrome浏览器·版本不同造成问题·弹框页面无法滚动
玩代码1 小时前
vue项目安装chromedriver超时解决办法
前端·javascript·vue.js
訾博ZiBo1 小时前
React 状态管理中的循环更新陷阱与解决方案
前端
StarPrayers.2 小时前
旅行商问题(TSP)(2)(heuristics.py)(TSP 的两种贪心启发式算法实现)
前端·人工智能·python·算法·pycharm·启发式算法
一壶浊酒..2 小时前
ajax局部更新
前端·ajax·okhttp
00后程序员张3 小时前
tcpdump 抓包分析,命令、过滤技巧、常见症状定位与移动真机补充方案
网络·测试工具·ios·小程序·uni-app·iphone·tcpdump
DoraBigHead3 小时前
React 架构重生记:从递归地狱到时间切片
前端·javascript·react.js