Vant 实现可多选与单选的表格组件

3,301 阅读1分钟

Vant 实现可多选与单选的表格组件

前言

楼主最近在使用Vant开发移动端,发现没有像element里的table组件,所以决定自己处理一个,功能包括:表格、单选、全选、取消全选以及某种状态的数据不可被选中

表现效果如下:

1.png

其中一些功能涉及公司业务,所以会有些省略。好了,废话不多说,直接上代码---

HTML

<div class="table_container">
    <div class="handle_area">
      <van-checkbox
        shape="square"
        class="all_checked"
        :disabled="disabled"
        v-model="allChecked"
        @click="toggleSelection"
        >全选/取消全选</van-checkbox
      >
    </div>
    <div class="list_content">
      <van-checkbox-group v-model="selectData" ref="checkboxGroup">
        <van-cell class="list_item" v-for="(item, index) in tableData" :key="item" :class="item.choosed ? 'selected_item' : ''">
          <div class="left">
            <div @click.stop>
               <van-checkbox
                  shape="square"
                  :name="item"
                  v-model="item.choosed"
                  :disabled="disabled"
                  @click="selectChange(item)"
                ></van-checkbox>
            </div>
           
            <div class="alias" :class="index % 2 == 0 ? 'odd_alias' : ''">
              {{ getAlias(item.name) }}
            </div>
            <div class="item_info">
              <div class="ellipsis">
                <span class="name">{{ item.name }}</span>
              </div>
              <siv class="dept ellipsis">{{ item.dept }}</siv>
            </div>
          </div>
          <div>
            <span class="edit-btn" @click="edit(item)">修改</span>
          </div>
        </van-cell>
      </van-checkbox-group>
    </div>
  </div>

JS

<script>
export default {
  props: ['tableData', 'index', 'disabled'],
  data() {
    return {
      selectData: [],
      allChecked: false,
    };
  },
  computed: {
      //获得列表中某种状态不能被选中以外的数据
    canCheckData() {
      let tableData = this.tableData;
      let arr = [],
        enableStatus = ['RUNNING', 'INIT'];
      for (let i = 0; i < tableData.length; i++) {
        if (enableStatus.includes(tableData[i].assessResult)) {
          arr.push(tableData[i]);
        }
      }
      return arr;
    },
  },
  mounted(){
    //初始化的时候要先把表格都置为不选中状态
    this.tableData.forEach(item => item['choosed'] = false)
  },
  methods: {
    // 获取别名
    getAlias(name) {
      if(!name) return '';
      return name.substring(name.length - 2);
    },
    //单选
    selectChange(val) {
      val.choosed = !val.choosed;
      //判断某种状态不能被选中以外的数据和选中数据的length长度是否相同,相同表示全选了,不同就不能全选了
      if (this.selectData.length === this.canCheckData.length) {
        this.allChecked = true;
      } else {
        this.allChecked = false;
      }
      //作为组件使用时可以把选中的数据向外发送
      this.$emit('selectChange', this.selectData);
    },
    // 全选
    toggleSelection() {
       //如果是全选,要通过toggleAll去选中列表中的所有数据,其中skipDisabled: true表示过滤掉禁用的复选框,checked为全选与取消全选的标志
      if (this.allChecked) {
        this.$refs.checkboxGroup.toggleAll({
          checked: true,
          skipDisabled: true表示过滤掉
        });
        this.selectData = this.canCheckData;
        this.$emit('selectChange', this.selectData);
      } else {
        this.$refs.checkboxGroup.toggleAll({
          checked: false,
          skipDisabled: true
        });
        this.$emit('selectChange', []);
      }
    },
    //列表编辑某一项,具体操作可在外层处理
    edit(item) {
      this.$emit('edit', item);     
    },
  },
};
</script>

CSS

<style lang="scss" scoped>
.table_container {
  margin-top: 8px;

  .handle_area {
    height: 45px;
    padding: 0 12px;
    display: flex;
    align-items: center;
    
    .all_checked {
      display: flex;
      align-items: center;
    }
  }
  .list_content {
    flex: 1;
    overflow: auto;

    .van-checkbox-group {
      background: white;
    }

    .selected_item {
      background-color: #f3f6fe;
    }

    .list_item {
      padding: 16px 12px;
      border-top: 1px solid #eeeeee;

      .van-cell__value {
        display: flex;
        align-items: center;
        justify-content: space-between;
      }

      .left {
        display: flex;
        align-items: center;
        width: 50%;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        
        .alias {
          display: inline-block;
          width: 40px;
          height: 40px;
          line-height: 40px;
          text-align: center;
          font-size: 14px;
          color: #fff;
          border-radius: 40px;
          background-color: #7f42f6;
          margin-left: 9px;
        }

        .odd_alias {
          background-color: #4273f6;
        }

        .item_info {
          margin-left: 12px;
          

          .ellipsis {
            white-space: nowrap;
            text-overflow: ellipsis;
            overflow: hidden;
            word-break: break-all;
          }

          .name {
            font-size: 17px;
            color: #333;
            line-height: 24px;
            font-weight: 500;
            height: 24px;
          }

          .dept {
            font-size: 15px;
            color: #999;
            line-height: 21px;
            height: 21px;
          }
        }
      }

      .arrow {
        width: 40px;
        height: 40px;
        position: relative;
        &::after {
          content: '';
          position: absolute;
          top: 15px;
          left: 15px;
          width: 10px;
          height: 10px;
          border: 2px solid #ccc;
          border-radius: 3px;
          border-left: none;
          border-bottom: none;
          transform: rotate(45deg);
        }
      }

      .edit-btn {
        margin-left: 12px;
        width: 60px;
        height: 30px;
        background: #ffffff;
        border: 1px solid #edeff1;
        border-radius: 12px;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 12px;
        font-weight: 400;
        color: #4273f6;
      }

      ::v-deep .van-checkbox {
        .van-checkbox__label {
          display: none;
        }
      }
    }
  }
  

  ::v-deep {
    .van-checkbox__icon {
      display: flex;
      align-items: center;

      .van-icon {
        width: 16px;
        height: 16px;
        line-height: 16px;
        border-color: #dedede;
        border-radius: 2px;
      }
    }
    .van-checkbox__label {
      margin-left: 9px;
      font-size: 15px;
      font-weight: 500;
      color: #333333;
    }
  }
}
</style>

结语

如果这篇文章帮到了你,欢迎点赞👍和关注⭐️。

文章如有错误之处,希望在评论区指正🙏🙏。

转载请注明出处🙏🙏。