微信小程序自用Tree树形控件

韩小韩
2022-01-04 / 0 评论 / 41 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2022年01月04日,已超过18天没有更新,若内容或图片失效,请留言反馈。

使用有赞的vant组件库开发微信小程序过程中,使用到了tree树形控件,但vant组件库无此组件,所以手撸了一个简陋二级tree树形控件

功能包含

全选按钮功能、反选按钮功能
父级列表前的开关icon
子级列表的选中的禁止或启用
父级列表显示子级列表可选数量
父级下所有可选子级选中则父选中(禁用状态不算)
使用了van-collapse组件带有折叠关闭动画效果
...

效果展示

微信小程序自用Tree树形控件

微信小程序自Tree树形控件 WXML代码部分

<van-collapse value="{{ activeNames }}" bind:change="onChange">
    <block wx:for="{{wrongList}}" wx:for-item="itm" wx:key="index">
      <van-collapse-item name="{{itm.code}}" data-hans="itm.code">
        <view slot="title">
          <image src="https://xxxx/{{KG[itm.code]!=true ?'open':'close'}}.png"
            style="width:20rpx" mode="widthFix" />
          {{itm.name}}
          <view catchtap="catchtap">
            <van-checkbox class="fuCheck" disabled="{{tempCodeArr[itm.code].length==0}}"
              value="{{ checkedAll[itm.code] }}" data-hans="{{itm.code}}" bind:change="checkcheck" />
            <view class="counts" style="right:106rpx">({{itm.fallibleCount}})</view>
          </view>
        </view>
        <view class="items">
          <van-checkbox-group value="{{ choisObj[itm.code] }}" data-hanscode="{{itm.code}}" bind:change="checkChange">
            <van-cell-group>
              <block wx:if="{{!_itm.hansFu}}" wx:for="{{ itm.children }}" wx:for-index="_index" wx:for-item="_itm"
                wx:key="code">
                <van-cell title="{{ _itm.name }}" value-class="value-class" clickable>
                  <van-checkbox name="{{ _itm.code }}" disabled="{{_itm.fallibleCount=='0'?true:false}}" />
                  <view class="counts">({{_itm.fallibleCount}})</view>
                </van-cell>
              </block>
            </van-cell-group>
          </van-checkbox-group>
        </view>
      </van-collapse-item>
    </block>
  </van-collapse>

微信小程序自Tree树形控件 JS部分

/*
 * @Author: Han
 * @Date: 2021-01-04 14:18:09
 * @LastEditors: Han
 * @LastEditTime: 2021-01-04 15:07:09
 * @FilePath: \wechat-app\tree.js
 */
import {
  get
} from 'api'
Page({
  data: {
    // 父级按钮合集
    checkedAll: [],
    // 面板状态合集
    activeNames: [],
    // 章节List
    wrongList: [],
    // 选中的子节点合集
    choisObj: {},
    // 临时 父 子 数组
    tempCodeArr: {},
    // 全选按钮状态
    selectAllStatus: true
  },
  // 全选事件
  selectAll() {
    const _this = this
    const status = this.data.selectAllStatus
    const okTempCodeArr = JSON.parse(JSON.stringify(_this.data.tempCodeArr))
    Object.keys(okTempCodeArr).forEach(itm => {
      okTempCodeArr[itm].length == 0 && delete okTempCodeArr[itm]
    })
    // 模拟点击
    Object.keys(okTempCodeArr).forEach(itm => {
      _this.checkChange({
        currentTarget: {
          dataset: {
            hanscode: itm
          }
        },
        detail: status ? okTempCodeArr[itm] : []
      })
    })
    this.setData({
      selectAllStatus: !status,
    })
  },
  // 父级按钮
  checkcheck(e) {
    const codes = e.currentTarget.dataset.hans
    // 判断父级按钮状态
    this.setData({
      checkedAll: {
        ...this.data.checkedAll,
        [codes]: e.detail
      },
      choisObj: {
        ...this.data.choisObj,
        [codes]: e.detail ? this.data.tempCodeArr[codes] : []
      }
    });
    // 去除空对象,并设置按钮状态
    const tempObj = this.data.choisObj
    Object.keys(tempObj).forEach(itm => {
      tempObj[itm].length == 0 && delete tempObj[itm]
    })
    this.setData({
      choisObj: tempObj,
      btnStatus: Object.keys(tempObj).length > 0
    })
  },
  // 子级按钮点击选中或非事件
  checkChange(e) {
    const codes = e.currentTarget.dataset.hanscode
    // 可选中的是否全选
    const status = e.detail.length == this.data.tempCodeArr[codes].length
    this.setData({
      choisObj: {
        ...this.data.choisObj,
        [codes]: e.detail
      },
      checkedAll: {
        ...this.data.checkedAll,
        [codes]: status
      }
    });
    const tempObj = this.data.choisObj
    Object.keys(tempObj).forEach(itm => {
      tempObj[itm].length == 0 && delete tempObj[itm]
    })
    this.setData({
      choisObj: tempObj,
      btnStatus: Object.keys(tempObj).length > 0
    })
  },
  // 折叠面板切换事件
  onChange(event) {
    let tempArr = []
    // 当前面板折叠状态 临时变量
    let key = false

    // 由于面板可以多个同时展开,所以 👇
    // 控制面板标题前 图片的 + 或 -
    if (this.data.activeNames.length > event.detail.length) {
      // 深拷贝
      tempArr = JSON.parse(JSON.stringify(this.data.activeNames))
      event.detail.forEach(itm => {
        const n = tempArr.indexOf(itm);
        n != -1 && tempArr.splice(n, 1)
      });
      key = false
    } else {
      tempArr = JSON.parse(JSON.stringify(event.detail))
      this.data.activeNames.forEach(itm => {
        const n = tempArr.indexOf(itm);
        n != -1 && tempArr.splice(n, 1)
      });
      key = true
    }
    this.setData({
      activeNames: event.detail,
      KG: {
        ...this.data.KG,
        [tempArr[0]]: key
      }
    });
  },
  // 切换事件
  onSwitchChange(e) {
    // 切换时,清空除额外所有数据
    this.setData({
      xx: [],
      xx: {},
      ...xx
    })
    // 之后重新获取列表
    this.XXX();
  },

  // 获取书本信息
  async getBookArr() {
    wx.showLoading({
      title: '获取数据中',
    })
    let tempArr = [];
    const _this = this
    const {
      ret: {
        bookList: _res
      }
    } = await get('api');
    wx.hideLoading()
    // 书本信息赋给下拉框
    Array.isArray(_res) && _res.forEach(itm => {
      tempArr.push({
        'text': itm.name,
        'value': itm.id
      })
    })
    tempArr.length > 0 && _this.setData({
      bookDataArr: tempArr
    })
  },
  // 获取章节列表
  async getWrongList() {
    const _this = this
    const _res = await get(`api`)
    let _tempArr = _res.ret.bookCatalogs;
    // 章节数据处理
    Array.isArray(_tempArr) && _tempArr.length > 0 && _tempArr.forEach((itm, idx) => {
      let tempArrs = []
      itm.fallibleCount = Number(itm.fallibleCount)
      itm.children.length > 0 ? itm.children.forEach(_itm => {
        itm.fallibleCount += Number(_itm.fallibleCount)
        _itm.fallibleCount != '0' && tempArrs.push(_itm.code)
      }) : _tempArr[idx].children.push({
        name: itm.name,
        code: itm.code,
        fallibleCount: itm.fallibleCount,
        hansFu: true
      })
      _this.setData({
        tempCodeArr: {
          ..._this.data.tempCodeArr,
          [itm.code]: tempArrs
        }
      })
    })
    _res.ret && this.setData({
      wrongList: _tempArr
    })
  },
  // 防止父级点击事件冒泡空事件
  catchtap() {}
})
0

评论 (0)

取消