vue3 + vant4 checkbox多选弹框

实现效果

代码如下

多选组件
DictSelect.vue

<template>
  <van-popup :show="showPicker" position="bottom" :style="{ height: '34vh' }">
    <div class="con">
      <div class="confirmBtns">
        <van-button class="qxBtn" @click="handleClose" size="normal"
          >取消</van-button
        >
        <div class="title" size="normal">{{ title }}</div>
        <van-button class="qrBtn" @click="onSubmit" size="normal"
          >确认</van-button
        >
      </div>
      <div class="checkboxCon">
        <van-cell v-if="showTotalBtn" title="全选">
          <template #right-icon>
            <van-checkbox
              v-model="isCheckAll"
              :indeterminate="isIndeterminate"
            />
          </template>
        </van-cell>
        <van-checkbox-group
          v-model="selectList"
          ref="checkboxGroup"
          @change="checkedResultChange"
        >
          <van-cell
            v-for="(item, index) in dataList"
            :key="index"
            :title="`${item.text}`"
          >
            <template #right-icon>
              <van-checkbox :name="item.value" />
            </template>
          </van-cell>
        </van-checkbox-group>
      </div>
    </div>
  </van-popup>
</template>

<script setup>
import { reactive, ref, watch, computed, onMounted } from "vue";

const props = defineProps({
  title: {
    type: String,
    default: ""
  },
  dataList: {
    type: Array,
    default: () => []
  },
  initSelectList: {
    type: Array,
    default: () => []
  },
  showTotalBtn: {
    type: Boolean,
    default: false
  }
});

const showPicker = ref(false);
const checkboxGroup = ref();
const isCheckAll = ref(false);
const isIndeterminate = ref(false); // 是否为不确定状态
const selectList = ref([...props.initSelectList]);

const emits = defineEmits(["handleSelect"]);

const handleOpen = () => {
  showPicker.value = true;
};

const handleClose = () => {
  showPicker.value = false;
  // onReset();
};

const onSubmit = () => {
  const selectListText = (selectList.value || []).map(s => {
    const current = props.dataList.find(d => d.value === s);
    return current?.text;
  });

  emits("handleSelect", { values: selectList.value, texts: selectListText });
  handleClose();
};

const checkedResultChange = value => {
  const checkedCount = value.length;
  isCheckAll.value = checkedCount === props.dataList.length;
  isIndeterminate.value =
    checkedCount > 0 && checkedCount < props.dataList.length;
};

watch(isCheckAll, (newValue, oldValue) => {
  if (newValue) {
    checkboxGroup.value.toggleAll(true);
    isIndeterminate.value = false;
  } else {
    checkboxGroup.value.toggleAll();
    isIndeterminate.value = false;
  }
});

defineExpose({
  handleOpen,
  handleClose
});
</script>

<style lang="less" scoped>
.con {
  .confirmBtns {
    display: flex;
    justify-content: space-between;
    height: 44px;
    line-height: 44px;

    .title {
      border: none;
      color: #000;
    }

    .qxBtn {
      border: none;
      color: #969799;
    }

    .qrBtn {
      border: none;
      color: #1989fa;
    }
  }

  .checkboxCon {
    width: 100%;
    height: calc(34vh - 44px);
    overflow-y: auto;
    padding: 10px 0;
  }
}
</style>

父组件使用:

<template>
  <van-field
    v-model="formObj.rangeText"
    name="rangeText"
    label="多选"
    label-align="top"
    placeholder="请输入"
    type="text"
    is-link
    readonly
    :rules="[{ required: true, message: '请选择' }]"
    @click="handlePicker"
  />
  <dict-select
    ref="pickerRef"
    title="请选择"
    showTotalBtn
    :dataList="dataList"
    :initSelectList="formObj.range"
    @handleSelect="onConfirm"
  />
</template>

<script setup>
import { ref } from "vue";

const pickerRef = ref();
const formObj = ref({
  range: ['1'],
  rangeText: ['选项一']
});
const dataList = ref([
  { value: "1", text: "选项一" },
  { value: "2", text: "选项二" },
  { value: "3", text: "选项三" },
  { value: "4", text: "选项四" }
]);

const onConfirm = ({ values, texts }) => {
  console.log("value", values, texts);
  formObj.value.range = values;
  formObj.value.rangeText = (texts || []).join(",");
};

const handlePicker = () => {
  pickerRef?.value?.handleOpen && pickerRef?.value?.handleOpen();
};
</script>
posted @ 2024-04-17 10:21  ZerlinM  阅读(555)  评论(0编辑  收藏  举报