paquete de selector de selección múltiple uniapp select

Prefacio: la función que el autor quiere implementar es similar a un selector uniapp, pero se pueden seleccionar múltiples valores y se pueden realizar una sola selección y todas las selecciones al mismo tiempo. Lo busqué en el marco de interfaz de usuario de uniapp y Descubrí que no existe uno similar. Finalmente, lo encontré en el mercado de complementos de uniapp. Las funciones en esta selección múltiple son relativamente completas. Puede realizar una selección única de todos y seleccionar múltiples valores al mismo tiempo. . También puedes desactivar ciertos datos. Hice algunos cambios y los registré. Espero que puedas usarlos en el futuro.

Encapsulación de componentes: multiple-select.vue

<template>
  <view class="select-container" v-show="show" @touchmove.stop.prevent>
    <view
      class="mask"
      :class="activeClass ? 'mask-show' : ''"
      @tap="onCancel(true)"
    ></view>
    <view class="select-box" :class="activeClass ? 'select-box-show' : ''">
      <view class="header">
        <text class="cancel" @tap="onCancel">{
   
   { cancelText }}</text>
        <view class="all" @tap="onAllToggle" v-if="allShow">
          <text :class="isAll ? 'all-active' : ''">全选 </text>
        </view>
        <text class="confirm" @tap="onConfirm">{
   
   { confirmText }}</text>
      </view>
      <view class="body-warp">
        <scroll-view class="body" scroll-y="true">
          <slot v-if="!data.length" name="tips">
            <view class="empty-tips">暂无数据~</view>
          </slot>
          <view
            class="select-item"
            :class="[
              item.disabled ? 'disabled' : '',
              selectedArr[index] ? 'selected' : '',
            ]"
            v-for="(item, index) in data"
            :key="item[valueName]"
            @tap="onSelected(index)"
          >
            <view class="label">{
   
   { item.name }}</view>
            <text v-show="selectedArr[index]" class="selected-icon">✔</text>
          </view>
        </scroll-view>
      </view>
    </view>
  </view>
</template>
<!-- 多选组件 -->
<script>
export default {
  model: {
    prop: "value",
    event: ["input"],
  },

  data() {
    return {
      show: false, //是否显示
      activeClass: false, //激活样式状态
      selectedArr: [], //选择对照列表
      selectedArrOld: [], //选择对照列表上一次的数据
    };
  },
  onShow() {
    this.show = this.value;
    console.log(this.serviceList);
  },
  computed: {
    // 返回是否全选
    isAll() {
      let wipeDisabledList = this.returnWipeDisabledList();
      if (!wipeDisabledList.length) return false;
      return !wipeDisabledList.includes(false);
    },
  },
  props: {
    // 双向绑定
    value: {
      type: Boolean,
      default: false,
    },
    // 取消按钮文字
    cancelText: {
      type: String,
      default: "取消",
    },
    // 确认按钮文字
    confirmText: {
      type: String,
      default: "确认",
    },
    // label对应的key名称
    labelName: {
      type: String,
      default: "label",
    },
    // value对应的key名称
    valueName: {
      type: String,
      default: "value",
    },
    // 是否允许点击遮罩层关闭
    maskCloseAble: {
      type: Boolean,
      default: true,
    },
    // 是否显示全选
    allShow: {
      type: Boolean,
      default: true,
    },
    // 模式
    mode: {
      type: String,
      default: "multiple",
    },
    // 默认选中值
    defaultSelected: {
      type: Array,
      default: function () {
        return [];
      },
    },
    // 数据源
    data: {
      type: Array,
      required: true,
      default: () => {
        return [];
      },
    },
  },
  created() {
    console.log(this.data, "111111");
  },
  watch: {
    async value(newVal) {
      this.show = newVal;
      await this.$nextTick();
      this.activeClass = newVal;
      if (newVal) {
        this.selectedArrOld = JSON.parse(JSON.stringify(this.selectedArr));
      }
    },
    async data(newVal) {
      this.data = newVal;
      await this.$nextTick();
      console.log(this.data);
    },
    show(newVal) {
      this.$emit("input", newVal);
      this.$emit("change", newVal);
    },
    data: {
      // 设置初始选择对照列表
      handler(list) {
        this.selectedArr = list.map((el) => false);
        this.setItemActiveState();
      },
      deep: true,
      immediate: true,
    },
    defaultSelected: {
      handler() {
        this.setItemActiveState();
      },
      deep: true,
      immediate: true,
    },
  },
  methods: {
    // 设置默认选中通用办法
    setItemActiveState() {
      if (this.data.length && this.defaultSelected.length) {
        this.data.forEach((item, i) => {
          for (let n = 0; n < this.defaultSelected.length; n++) {
            if (
              !item.disabled &&
              item[this.valueName] === this.defaultSelected[n]
            ) {
              this.selectedArr.splice(i, 1, true);
              break;
            }
          }
        });
      }
    },
    /**
     * 选择事件
     * @index {Number} 点击下标
     */
    onSelected(index) {
      if (this.data[index].disabled) return;
      let index2Active = this.selectedArr[index];
      this.selectedArr.splice(index, 1, !index2Active);
    },
    // 取消事件
    onCancel(isMask) {
      if (!isMask || this.maskCloseAble) {
        this.show = false;
        this.selectedArr = JSON.parse(JSON.stringify(this.selectedArrOld));
      } else {
        return;
      }
      this.$emit("cancel");
    },
    // 返回去除了disabled状态后的对照列表
    returnWipeDisabledList() {
      let arr = [];
      this.selectedArr.forEach((el, index) => {
        if (!this.data[index].disabled) arr.push(el);
      });
      return arr;
    },
    // 全选/非全选事件
    onAllToggle() {
      let wipeDisabledList = this.returnWipeDisabledList();
      // 如果去除了disabled的对照列表有false的数据,代表未全选
      if (wipeDisabledList.includes(false)) {
        this.selectedArr.forEach((el, index) => {
          if (!this.data[index].disabled)
            this.selectedArr.splice(index, 1, true);
        });
      } else {
        this.selectedArr.forEach((el, index) => {
          if (!this.data[index].disabled)
            el = this.selectedArr.splice(index, 1, false);
        });
      }
    },
    // 确定事件
    onConfirm() {
      console.log(11212);
      this.show = false;
      let selectedData = [];
      this.selectedArr.forEach((el, index) => {
        if (el) {
          console.log(el);
          selectedData.push(this.data[index]);
        }
      });
      if (this.mode === "multiple") {
        console.log(selectedData);
        this.$emit("confirm", selectedData);
      } else {
        let backData = selectedData[0] || {};
        this.$emit("confirm", backData);
      }
    },
  },
};
</script>
<style lang="scss" scoped>
.select-container {
  width: 100vw;
  height: 100vh;
  position: fixed;
  left: 0;
  top: 0;
  z-index: 999;
  $paddingLR: 18rpx;
  .mask {
    width: 100%;
    height: 100%;
    background-color: $uni-bg-color-mask;
    opacity: 0;
    transition: opacity 0.3s;
    &.mask-show {
      opacity: 1;
    }
  }
  // 选择器内容区域
  .select-box {
    width: 100%;
    position: absolute;
    bottom: 0;
    left: 0;
    transform: translate3d(0px, 100%, 0px);
    background-color: $uni-bg-color;
    transition: all 0.3s;
    &.select-box-show {
      transform: translateZ(0);
    }
    .header {
      display: flex;
      box-sizing: border-box;
      width: 100%;
      justify-content: space-between;
      border-bottom: 1px solid $uni-border-color;
      line-height: 76rpx;
      font-size: 30rpx;
      padding: 0 $paddingLR;
      .cancel {
        color: $uni-text-color-grey;
      }
      .all {
        color: $uni-color-success;
        .all-active {
          &::after {
            display: inline-block;
            content: "✔";
            padding-left: 8rpx;
          }
        }
      }
      .confirm {
        color: $uni-color-primary;
      }
    }
    .body-warp {
      width: 100%;
      height: 30vh;
      box-sizing: border-box;
      padding: 20rpx $paddingLR;
    }
    .body {
      width: 100%;
      height: 100%;
      overflow-y: auto;
      .empty-tips {
        margin-top: 25%;
        text-align: center;
        font-size: 26rpx;
        color: $uni-color-error;
      }
      .select-item {
        display: flex;
        font-size: 26rpx;
        line-height: 58rpx;
        color: #303133;
        position: relative;
        transition: all 0.3s;
        &.selected {
          color: $uni-color-primary;
        }
        &.disabled {
          color: $uni-text-color-disable;
        }
        > .label {
          flex: 1;
          text-align: center;
        }
        > .selected-icon {
          position: absolute;
          right: 0;
          top: 50%;
          transform: translateY(-50%);
        }
      }
    }
  }
}
</style>

Utilizado dentro de los componentes:

<template>
  <view class="wrap">
   <multiple-select
      v-model="accServiceShow"
      :data="serviceList"
      :default-selected="defaultSelected"
      @confirm="accServiceConfirm"
    ></multiple-select>
  </view>
</template>
<script>
import multipleSelect from "../../components/multiple-select/multiple-select.vue";
export default {
  components: {
    multipleSelect,
  },
  data(){
     return{
        defaultSelected: ["3", "5"], //默认选中项
        serviceList: [],//传递给子组件的数据
    }
}

</script>

Nota: Este complemento no es el autor original. Si hay alguna infracción, comuníquese con el autor para eliminarlo.

Supongo que te gusta

Origin blog.csdn.net/weixin_53561783/article/details/127916678
Recomendado
Clasificación