[微信小程序]记一次微信小程序的自定义组件2

[微信小程序]自定义组件—下拉选择

小程序项目中需要使用下拉框组件 本想使用原生选择器 但是需求必须完全还原设计图 无奈参考网上各路大神 记录一下自定义组件
效果图

第一步在json中需要配置:
component 为 true 设为自定义组件
singComponent 作为引用组件的页面的json的声明配置项,值为引用的组件路径。

JSON

// An highlighted block
{
  "component": true,
  "usingComponent": {}
}

wxml中写组件的基本结构和需要绑定的属性,值和事件
tapDistrictNav : 下拉框折叠事件
selectDistrictLeft : 区域下拉联动父级事件
selectItems : 选中值的点击方法

data-nav: 用来判断当前下拉框的值
data-model : 具体值

ps:这里没有进行代码精简优化 算是比较糙的一版 后期可以改进一下

WXML

// An highlighted block
<view class="nav">
  <view class="nav-child {{folding_open1? 'active' : ''}}" bindtap="tapDistrictNav" hidden='{{dropDownMenuDistrictData.length > 0 ? false :true}}' data-nav="{{dropDownMenuTitle[0]}}">
    <view class="nav-title">{{district_right_select_name.length > 0 ?district_right_select_name : dropDownMenuTitle[0]}}</view>
    <view class="icon"></view>
  </view>
  <view class="nav-child borders {{folding_open2? 'active' : ''}}" bindtap="tapDistrictNav" hidden='{{dropDownMenuSourceData.length > 0 ? false : true}}' data-nav="{{dropDownMenuTitle[1]}}">
    <view class="nav-title">{{selected_source_name.length > 0 ?selected_source_name : dropDownMenuTitle[1]}}</view>
    <view class="icon"></view>
  </view>
  <view class="nav-child borders-right {{folding_open3? 'active' : ''}}" bindtap="tapDistrictNav" hidden='{{dropDownMenuStyleData.length > 0 ? false : true}}' data-nav="{{dropDownMenuTitle[2]}}">
    <view class="nav-title">{{selected_style_name.length > 0 ?selected_style_name : dropDownMenuTitle[2]}}</view>
    <view class="icon"></view>
  </view>
  <view class="nav-child {{folding_open4 ? 'active' : ''}}" bindtap="tapDistrictNav" hidden='{{dropDownMenuFilterData.length > 0 ? false : true}}' data-nav="{{dropDownMenuTitle[3]}}">
    <view class="nav-title">{{selected_filter_name.length > 0 ?selected_filter_name : dropDownMenuTitle[3]}}</view>
    <view class="icon"></view>
  </view>
</view>

<view class="district {{folding_open1 ? 'show' : 'disappear'}} ">
  <view class="half half-left">
    <view 
      class="{{district_left_select == item.id ? 'current_left_select' : ''}}" 
      wx:for="{{dropDownMenuDistrictData}}" 
      bindtap="selectDistrictLeft" 
      data-model='{{item}}' 
      wx:key="unique">
      {{item.title}}
    </view>
  </view>
  <view class="half half-right">
    <view 
      class="{{district_right_select == item.id ? 'current_right_select' : ''}}" 
      wx:for="{{dropDownMenuDistrictDataRight}}" 
      bindtap="selectItems" 
      data-model='{{item}}' 
      data-nav="{{dropDownMenuTitle[0]}}"
      wx:key="unique">
      {{item.title}}
    </view>
  </view>
</view>

<view class="container container_hd {{folding_open2 ? 'show' : 'disappear'}} ">
  <view class='z-height'>
    <view>
      <block wx:for="{{dropDownMenuSourceData}}" wx:key="unique">
        <view 
          class="sortitem {{selected_source_id==item.id ? ' active ' : ' '}}"  
          data-model='{{item}}' 
          data-nav="{{dropDownMenuTitle[1]}}"
          bindtap='selectItems'> 
          {{item.title}}
        </view>
      </block>
    </view>
  </view>
</view>
<view class="container container_hd {{folding_open3 ? 'show' : 'disappear'}} ">
  <view class='z-height'>
    <view>
      <block wx:for="{{dropDownMenuStyleData}}" wx:key="unique">
        <view 
          class="sortitem {{selected_style_id==item.id ? ' active ' : ' '}}" 
          data-model='{{item}}' 
          data-nav="{{dropDownMenuTitle[2]}}"
          bindtap='selectItems'> 
          {{item.title}}
        </view>
      </block>
    </view>
  </view>
</view>
<view class="container container_hd {{folding_open4 ? 'show' : 'disappear'}} ">
  <view class='z-height'>
    <view>
      <block wx:for="{{dropDownMenuFilterData}}" wx:key="unique">
        <view 
          class="sortitem {{selected_filter_id==item.id ? ' active ' : ' '}}" 
          data-model='{{item}}' 
          data-nav="{{dropDownMenuTitle[3]}}"
          bindtap='selectItems'> 
          {{item.title}}
        </view>
      </block>
    </view>
  </view>
</view>

wxss样式不多说 没什么需要改动 引用时可以用margin或者定位改变在父组件位置

WXSS

// An highlighted block
.page {
  width: 100%;
  height: 100%;
  background: #fff;
  overflow: hidden;
}

.position {
  position: absolute;
}

.nav {
  position: relative;
  z-index: 99;
  display: flex;
  border-bottom: 1px solid #f7f7f7;
  background: #fff;
}

.nav-child {
  display: flex;
  flex: 1;
  text-align: center;
  height: 48rpx;
  align-items: center;
  justify-content: center;
  font-size: 24rpx;
  margin: 20rpx 0;
}

.borders-right {
  border-right: 1px solid #e6e6e6;
}

.borders-left {
  border-left: 1px solid #e6e6e6;
}

.borders {
  border-left: 1px solid #e6e6e6;
  border-right: 1px solid #e6e6e6;
}

.nav-title {
  display: inline-block;
}

.icon {
  display: inline-block;
  border: 4px solid transparent;
  border-top: 4px solid #9b9b9b;
  margin-left: 5px;
  margin-top: 10rpx;
}

.container {
  position: relative;
  z-index: 4;
  font-size: 14px;
}


.slidedown {
  transform: translateY(0%);
}

.district {
  position: absolute;
  display: none;
  z-index: 5;
  width: 100%;
  height: 100%;
  overflow-y: scroll;
  background-color: rgba(0, 0, 0, 0.5);
}

.district .half {
  overflow-y: scroll;
  float: left;
  width: 50%;
  height: 600rpx;
  line-height: 80rpx;
  box-sizing: border-box;
  font-size: 14px;
}

.half view {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  padding-left: 15rpx;
}

.half-left {
  background: #f7f7f7;
}

.half-center {
  background: #fff;
}

.half-right {
  background: #fff;
}

.half-right view {
  border-bottom: 1px solid #f7f7f7;
}

.current_left_select {
  background: #fff;
}

.current_right_select {
  background: #fff;
  color: #E22317;
}

.nav-child.active .nav-title {
  color: #E22317;
}

.nav-child.active .icon {
  border-bottom: 4px solid #E22317;
  border-top: 0;
}

@keyframes slidown {
  from {
    transform: translateY(-100%);
  }

  to {
    transform: translateY(0%);
  }
}

.slidown {
  display: block;
  animation: slidown 0.2s ease-in both;
}

@keyframes slidup {
  from {
    transform: translateY(0%);
  }

  to {
    transform: translateY(-100%);
  }
}

.z-height {
  overflow-y: scroll;
  background: #fff;
}

.slidup {
  display: block;
  animation: slidup 0.2s ease-in both;
}

.disappear {
  display: none;
}

.show {
  display: block;
}

.slidowntop {
  display: flex;
  flex-direction: row;
  padding: 20rpx 24rpx 10rpx 24rpx;
}

.emptyall {
  margin-left: 475rpx;
  color: #E22317;
}

.emptyallright {
  width: 80rpx;
  text-align: center;
}

.endselect {
  width: 350rpx;
  text-align: left;
}

.return {
  margin-left: 200rpx;
  color: #E22317;
}

.slidowncenter {
  margin-top: 20rpx;
  padding-top: 20rpx;
  padding-left: 24rpx;
  display: flex;
  flex-direction: row;
  align-content: space-between;
  border-top: solid #d1d3d4 1rpx;
}

.slidownbottom {
  margin-top: 10rpx;
  padding: 10rpx;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}

.sortitem {
  border-bottom: solid #f7f7f7 1rpx;
  justify-content: space-between;
  padding: 20rpx 30rpx;
}

.sortitem.active {
  color: #E22317;
}

.container_hd {
  width: 100%;
  height: 100%;
  position: absolute;
  overflow-y: scroll;
  background-color: rgba(0, 0, 0, 0.5);
}

组件js 同wxml 代码比较糙 因为开始假设区域是静态数据 所以方法有待改进 可以只传一个当前行政区划代码 在组件里进行请求 获取数据

JS

// An highlighted block
Component({
  properties: {
    dropDownMenuTitle: {
      type: Array,
      value: [],
    },
    dropDownMenuDistrictData: {
      type: Array,
      value: [],
      observer: function(newVal, oldVal) {
        console.log(newVal,oldVal)
        let model = newVal[0] ? newVal[0] : null
        this.selectDefaltDistrictLeft(model)
      }
    },

    dropDownMenuSourceData: {
      type: Array,
      value: []
    },
    dropDownMenuStyleData: {
      type: Array,
      value: []
    },
    dropDownMenuFilterData: {
      type: Array,
      value: []
    },
  },
  data: {
    // private properity
    folding_open1:false,      //区域
    folding_open2:false,      //来源
    folding_open3:false,      //租售状态
    folding_open4:false,      //排序
    shownavindex: '',
    dropDownMenuDistrictDataRight: {},
    district_left_select: '',
    district_right_select: '',
    district_right_select_name: '',
    selected_style_id: 0,
    selected_style_name: '',
    selected_source_id: 0,
    selected_source_name: '',
    selected_filter_id: 0,
    selected_filter_name: '',
  },
  methods: {
    
    //全部折叠
    foldingSetData(){
      this.setData({
        folding_open1: false,
        folding_open2: false,
        folding_open3: false,
        folding_open4: false,
        shownavindex: 0
      })
    },
    //收起展开
    tapDistrictNav: function(e) {
      // console.log(e)
      let navId = e.currentTarget.dataset.nav;
      let navName = e._relatedInfo.anchorTargetText
      // console.log("nav",navId)
      if (this.data.folding_open1 || this.data.folding_open2 || this.data.folding_open3 || this.data.folding_open4) {
        this.foldingSetData()
      }else{
        switch(true) {
          case navId == '区域':
              this.setData({
                folding_open1: true,
                shownavindex: e.currentTarget.dataset.nav
              })
             break;
          case navId == '来源':
              this.setData({
                folding_open2: true,
                shownavindex: e.currentTarget.dataset.nav
              })
             break;
          case navId == '租售':
              this.setData({
                folding_open3: true,
                shownavindex: e.currentTarget.dataset.nav
              })
            break
          case navId == '排序':
              this.setData({
                folding_open4: true,
                shownavindex: e.currentTarget.dataset.nav
              })
            break
          default:
            this.foldingSetData()
        }  
      }
      // console.log(e)
    },
    selectDefaltDistrictLeft(model) {
      if (!model) {
        return
      }
      var model = model.childModel;
      // console.log("model",model)
      var selectedId = model.id
      var selectedTitle = model.title;
      this.setData({
        dropDownMenuDistrictDataRight: model ? model : '',
        district_left_select: selectedId,
        district_right_select: '',
      })
    },
    //
    selectDistrictLeft: function(e) {
      var model = e.target.dataset.model.childModel;
      var selectedId = e.target.dataset.model.id
      var selectedTitle = e.target.dataset.model.title;
      this.setData({
        dropDownMenuDistrictDataRight: model ? model : '',
        district_left_select: selectedId,
        district_right_select: '',
      })
    },
    // 提炼代码
    selectItems(e){
      console.log(e)
      let navId = e.currentTarget.dataset.nav;
      let selectedId = e.target.dataset.model.id
      let selectedTitle = e.target.dataset.model.title;
      this.closeHyFilter();
      if(navId == '区域'){
        this.setData({
          district_right_select: selectedId,
          district_right_select_name: selectedTitle
        })
      }else if(navId == '来源'){
        this.setData({
          selected_source_id: selectedId,
          selected_source_name: selectedTitle
        })
      }else if(navId == '租售'){
        this.setData({
          selected_style_id: selectedId,
          selected_style_name: selectedTitle
        })
      }else if(navId == '排序'){
        this.setData({
          selected_filter_id: selectedId,
          selected_filter_name: selectedTitle
        })
      }
      this.triggerEvent("selectedItem", {
        index: this.data.shownavindex,
        selectedId: selectedId,
        selectedTitle: selectedTitle
      })
    },
    /*关闭筛选 */
    closeHyFilter: function() {
      if (this.data.folding_open1 || this.data.folding_open2 || this.data.folding_open3 || this.data.folding_open4) {
        this.foldingSetData()
      }
    },
  },
  //组件生命周期函数,在组件实例进入页面节点树时执行
  attached: function() {


  },

})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值