当前位置: 首页>前端>正文

elementui穿梭框传递多个值 element ui穿梭框分页

封装穿梭框

elementui穿梭框传递多个值 element ui穿梭框分页,elementui穿梭框传递多个值 element ui穿梭框分页_elementui穿梭框传递多个值,第1张

elementui穿梭框传递多个值 element ui穿梭框分页,elementui穿梭框传递多个值 element ui穿梭框分页_前端_02,第2张

利用element组件封装了一个包含前端分页,查询,全选所有,全选当页,反选功能的穿梭框。
纯手动封装,如有建议欢迎评论探讨。话不多说,直接上代码!

组件文件
<template>
  <div class="transfer">
    <div class="left-box card-box">
      <div class="box-top">
        <el-dropdown placement="bottom-start">
          <span class="el-dropdown-link">
            <i class="el-icon-arrow-down icon-margin"></i>
          </span>
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item @click.native="chooseAll('left')">全选所有</el-dropdown-item>
            <el-dropdown-item @click.native="chooseCurrentAll('left')">全选当页</el-dropdown-item>
            <el-dropdown-item @click.native="chooseReverse('left')">反选当页</el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
        <span class="total-tip">{{`${leftCheckList.length}/${leftTotal}台`}}</span>
        <span class="title-tip">{{titles[0]}}</span>
      </div>
      <div class="box-content">
        <div class="search-margin">
          <el-input
            :placeholder="filterPlaceholder"
            prefix-icon="el-icon-search"
            size="small"
            v-model="leftSearch"
            clearable
            @input="searchClick($event,'left')"
          ></el-input>
        </div>
        <div class="checkbox-group">
          <el-checkbox-group v-model="leftCheckKeys">
            <el-checkbox
              class="wrap-text"
              v-for="item in leftTransferDataList"
              @change="handleCheck($event, item, 'left')"
              :key="item.value"
              :label="item.label"
            ></el-checkbox>
          </el-checkbox-group>
        </div>
      </div>
      <div class="box-bottom">
        <el-pagination
          small
          slot="left-footer"
          @current-change="handleCurrentChange($event,'left')"
          :current-page="leftPageOption.currentPage"
          :page-size="leftPageOption.pageSize"
          layout="prev, pager, next, jumper"
          :total="leftPageOption.total"
        ></el-pagination>
      </div>
    </div>
    <div class="buttons-box">
      <el-button
        type="primary"
        icon="el-icon-arrow-right"
        :disabled="leftCheckList.length<1"
        @click="transferData('toRight')"
      ></el-button>
      <el-button
        type="primary"
        icon="el-icon-arrow-left"
        :disabled="rightCheckList.length<1"
        @click="transferData('toLeft')"
      ></el-button>
    </div>
    <div class="right-box card-box">
      <div class="box-top">
        <el-dropdown placement="bottom-start">
          <span class="el-dropdown-link">
            <i class="el-icon-arrow-down icon-margin"></i>
          </span>
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item @click.native="chooseAll('right')">全选所有</el-dropdown-item>
            <el-dropdown-item @click.native="chooseCurrentAll('right')">全选当页</el-dropdown-item>
            <el-dropdown-item @click.native="chooseReverse('right')">反选当页</el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
        <span class="total-tip">{{`${rightCheckList.length}/${rightTotal}台`}}</span>
        <span class="title-tip">{{titles[1]}}</span>
      </div>
      <div class="box-content">
        <div class="search-margin">
          <el-input
            :placeholder="filterPlaceholder"
            prefix-icon="el-icon-search"
            size="small"
            v-model="rightSearch"
            clearable
            @input="searchClick($event,'right')"
          ></el-input>
        </div>
        <div class="checkbox-group">
          <el-checkbox-group v-model="rightCheckKeys">
            <el-checkbox
              class="wrap-text"
              v-for="item in rightTransferDataList"
              :key="item.value"
              :label="item.label"
              @change="handleCheck($event, item, 'right')"
            ></el-checkbox>
          </el-checkbox-group>
        </div>
      </div>
      <div class="box-bottom">
        <el-pagination
          small
          slot="right-footer"
          @current-change="handleCurrentChange($event,'right')"
          :current-page="rightPageOption.currentPage"
          :page-size="rightPageOption.pageSize"
          layout="prev, pager, next, jumper"
          :total="rightPageOption.total"
        ></el-pagination>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: "transferPage",
  props: {
    titles: {
      type: Array,
      default: () => ["待选列表", "已选列表"],
    },
    filterPlaceholder: {
      type: String,
      default: '请输入内容',
    },
    // 可筛选
    filterable: {
      type: Boolean,
      default: false,
    },
    // 左侧数据
    leftTransferData: {
      type: Array,
      default: () => []
    },
    // 右侧数据
    rightTransferData: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      leftOriginDataList: [], // 源数据(未经过搜索过滤)
      leftAllDataList: [], // 分页前的数据
      leftTransferDataList: [], // 左侧展示列表(当前页)
      leftCheckKeys: [], // 左侧被选中数据的label
      leftCheckList: [], // 左侧被选中的数据列表
      leftSearch: '', // 左侧搜索数据
      leftPageOption: {
        currentPage: 1, //当前页
        pageSize: 10, //默认的每页显示条数
        total: 0 //总条目数
      },

      rightOriginDataList: [], // 源数据
      rightAllDataList: [], // 分页前的数据
      rightTransferDataList: [],
      rightCheckKeys: [],
      rightCheckList: [],
      rightSearch: '',
      rightPageOption: {
        currentPage: 1, //当前页
        pageSize: 10, //默认的每页显示条数
        total: 0 //总条目数
      },
      search: {
        code: "",
        name: "",
      }, //存储搜索框中填入的内
      stashSearch: {
        code: "",
        name: "",
      }, //暂存的搜索列表

    }
  },
  computed: {
    leftTotal() {
      return this.leftOriginDataList.length
    },
    rightTotal() {
      return this.rightOriginDataList.length
    },
  },
  watch: {
    // 源数据改变
    leftTransferData: {
      handler() {
        this.leftOriginDataList = JSON.parse(JSON.stringify(this.leftTransferData))
        this.rightOriginDataList = JSON.parse(JSON.stringify(this.rightTransferData))
        this.leftAllDataList = JSON.parse(JSON.stringify(this.leftTransferData))
        this.rightAllDataList = JSON.parse(JSON.stringify(this.rightTransferData))
        this.init()
      },
      deep: true,
      immediate: true,
    },
    // 源数据改变,重新分页
    rightOriginDataList: {
      handler() {
        this.$emit('transferChange', this.rightOriginDataList)
      },
      deep: true,
    },
  },
  methods: {
    init() {
      this.leftOriginDataList = JSON.parse(JSON.stringify(this.leftTransferData))
      this.rightOriginDataList = JSON.parse(JSON.stringify(this.rightTransferData))
      this.leftAllDataList = JSON.parse(JSON.stringify(this.leftTransferData))
      this.rightAllDataList = JSON.parse(JSON.stringify(this.rightTransferData))
      this.handleDataChange()
    },
    // 全选所有
    chooseAll(type) {
      this[`${type}CheckList`] = this[`${type}AllDataList`]
      this[`${type}CheckKeys`] = this[`${type}AllDataList`].map(item => item.label)
    },
    // 全选当页
    chooseCurrentAll(type) {
      this[`${type}CheckList`] = this[`${type}TransferDataList`]
      this[`${type}CheckKeys`] = this[`${type}TransferDataList`].map(item => item.label)
      this.$forceUpdate()
    },
    // 反选当页
    chooseReverse(type) {
      let currentCheck = this[`${type}CheckKeys`]
      this[`${type}CheckList`] = this[`${type}TransferDataList`].filter(item => !currentCheck.includes(item.label)
      )
      this[`${type}CheckKeys`] = this[`${type}CheckList`].map(item => item.label)
    },
    // 选中回调
    handleCheck(event, data, type) {
      if (event) {
        // 如果是选中
        this[`${type}CheckList`].push(data)
      } else {
        // 如果是取消
        this[`${type}CheckList`].splice(this[`${type}CheckList`].map(item => item.label).indexOf(data.label), 1)
      }
    },
    // 数据穿梭
    transferData(type) {
      if (type == 'toLeft') {
        // 1. 将右侧选中内容放入左侧数组
        this.leftOriginDataList.unshift(...this.rightCheckList)
        // 2. 清除右侧数组中的被选中数据
        this.rightOriginDataList = JSON.parse(JSON.stringify(this.rightOriginDataList.filter(item =>
          !this.rightCheckKeys.includes(item.label))
        ))
        // 3. 清空右侧选中数组,右侧选中标签数组
        this.rightCheckList = []
        this.rightCheckKeys = []
      } else if (type == 'toRight') {
        // 1. 将左侧选中内容放入右侧数组
        this.rightOriginDataList.unshift(...this.leftCheckList)
        // 2. 清除左侧数组中的被选中数据
        this.leftOriginDataList = JSON.parse(JSON.stringify(this.leftOriginDataList.filter(item =>
          !this.leftCheckKeys.includes(item.label))
        ))
        // 3. 清空左侧选中数组,左侧选中标签数组
        this.leftCheckList = []
        this.leftCheckKeys = []
      }
      this.handleDataChange()
    },
    // 数据穿梭后及数据初始化的数据处理
    handleDataChange() {
      // 1. origin源数据发生变化,根据搜索条件,让allDataList随之变化
      // 搜索过滤会做的事: 根据搜索框内容过滤源数据, 分页(此处多了一次无用的分页)
      this.searchFilter('left')
      this.searchFilter('right')
      // 2. 拿到正确的allDataList,处理分页数据:total,currentPage
      this.leftPageOption.total = this.leftAllDataList.length
      this.rightPageOption.total = this.rightAllDataList.length
      // 穿梭后,如果当前框内数据不足currentPage页,则后退一页
      if (this.leftPageOption.total !== 0 && this.leftPageOption.total <= ((this.leftPageOption.currentPage - 1) * this.leftPageOption.pageSize)) {
        this.leftPageOption.currentPage--
      }
      // 穿梭后,如果当前框内数据不足currentPage页,则后退一页
      if (this.rightPageOption.total !== 0 && this.rightPageOption.total <= ((this.rightPageOption.currentPage - 1) * this.rightPageOption.pageSize)) {
        this.rightPageOption.currentPage--
      }
      // 3. 分页,也就是拿到正确的TransferDataList
      this.leftTransferDataList = this.handleData(this.leftAllDataList, this.leftPageOption)
      this.rightTransferDataList = this.handleData(this.rightAllDataList, this.rightPageOption)
      // this.$forceUpdate()
    },
    //搜索功能 
    searchFilter(type) {
      this[`${type}Search`] = this[`${type}Search`] ? this[`${type}Search`].trim() : ""
      let filterList = []
      // 没有搜索内容时,让未分页的经过筛选数据等于源数据
      if (!this[`${type}Search`]) {
        filterList = JSON.parse(JSON.stringify(this[`${type}OriginDataList`]))
      } else {
        filterList = this[`${type}OriginDataList`].filter((item) =>
          item.label?.includes(this[`${type}Search`])
        )
      }
      this.$set(this[`${type}PageOption`], 'total', filterList.length)
      this[`${type}AllDataList`] = filterList
      // 对过滤后的数据,分页
      this[`${type}TransferDataList`] = this.handleData(this[`${type}AllDataList`], this[`${type}PageOption`])
      this.$forceUpdate()
    },
    //搜索点击
    searchClick(value, type) {
      this.$set(this[`${type}PageOption`], 'currentPage', 1)
      this[`${type}Search`] = value
      this.searchFilter(type)
    },
    // 处理数据分页 allDataList-经过筛选的数据列表,pageOption-分页数据
    handleData(allDataList, pageOption) {
      let start = (pageOption.currentPage - 1) * pageOption.pageSize
      let end = (start + pageOption.pageSize)
      // >pageOption.total?pageOption.total:(start + pageOption.pageSize)
      let currentPageList = []
      currentPageList = allDataList.slice(start, end)
      return currentPageList
    },
    //跳页回调
    handleCurrentChange(val, type) {
      this.$set(this[`${type}PageOption`], 'currentPage', val)
      this[`${type}TransferDataList`] = this.handleData(this[`${type}AllDataList`], this[`${type}PageOption`])
    },
  }
}
</script>

<style lang="scss" scoped>
::v-deep .el-dropdown-menu__item {
  span{
    width: 100%;
    height: 100%;
  }
}
::v-deep .el-pager li.active {
  color: #004BAA;
}
::v-deep .el-pager li:hover, ::v-deep .el-pagination button:hover {
  color: #407ecf;
}
::v-deep .el-dropdown-menu__item:focus, .el-dropdown-menu__item:not(.is-disabled):hover {
  background-color: #F5F7FA;
  color: #303133;
}
// 按钮禁用样式
::v-deep button.el-button.el-button--primary.el-button--small.is-disabled {
  background-color: #EFEFEF;
  border: 1px solid #CCC;
  color: #303133;
}
::v-deep button.el-button.el-button--primary.el-button--small.is-disabled:hover {
  background-color: #EFEFEF !important;
  border: 1px solid #CCC !important;
  color: #303133 !important;
}
.transfer {
  width: 100%;
  min-width: 680px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  .card-box {
    width: 40%;
    min-width: 300px;
    border: 1px solid #EBEEF5;
    border-radius: 4px;
    overflow: hidden;
    background: #FFF;
  }
  .box-top {
    display: flex;
    align-items: center;
    height: 40px;
    line-height: 40px;
    padding: 8px 12px 9px;
    background: #F5F7FA;
    border-bottom: 1px solid #EBEEF5;
    .icon-margin {
      font-size: 16px;
    }
    .total-tip {
      padding: 0 5px;
    }
    .title-tip {
      font-size: 16px;
      color: #303133;
      font-weight: 400;
    }
  }
  .box-content {
    width: 100%;
    border-bottom: 1px solid #EBEEF5;
    .search-margin {
      margin: 15px;
    }
    .checkbox-group {
      padding: 0 15px;
      height: 300px;
      overflow-x: hidden;
      overflow-y: auto;
      ::v-deep .el-checkbox{
        width: 100%;
        height: 30px;
        line-height: 30px;
        display: flex;
        align-items: center;
      }
      ::v-deep .el-checkbox__label {
        width: 100%;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
    }
  }
  .box-bottom {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    height: 40px;
    padding-right: 15px;
  }
  .buttons-box {
    width: 18%;
    min-width: 40px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    button {
      margin: 0 0 15px 0;
    }
  }
}
</style>
使用实例:

当前设置穿梭框最小宽度为680px,最大宽度由box-width定义的宽度决定

<template>
  <div>
    <my-transfer
      class="box-width"
      :titles="['待选列表', '已选列表']"
      :filterable="true"
      filterPlaceholder="请输入"
      :leftTransferData="deviceData"
      @transferChange="transferChange"
    ></my-transfer>
  </div>
</template>

<script>
//引入组件
import MyTransfer from '@/components/Transfer/index.vue'

export default {
  components: {
    MyTransfer,
  },
  data() {
    return {
      deviceData: [
        {label:'待选内容1',value:0},
        {label:'待选内容2',value:1},
        {label:'待选内容3',value:2},
        {label:'待选内容4',value:3},
        {label:'待选内容5',value:4},
        {label:'待选内容6',value:5},
        {label:'待选内容7',value:6},
        {label:'待选内容8',value:7},
        {label:'待选内容9',value:8},
        {label:'待选内容10',value:9},
        {label:'待选内容11',value:10},
        {label:'待选内容12',value:11},
        {label:'待选内容13',value:12},
        {label:'待选内容14',value:13},
        {label:'待选内容15',value:14},
        {label:'待选内容16',value:15},
        {label:'待选内容17',value:16},
        {label:'待选内容18',value:17},
        {label:'待选内容19',value:18},
      ],
      chooseDeviceList: [],
    }
  },
  methods: {
    // 获取最新的右侧数据
    transferChange(data) {
      this.chooseDeviceList = data
    },
  }
}
</script>
<style scoped>
/* 盒子宽度 */
.box-width {
  width: 1000px;
}
</style>



https://www.xamrdz.com/web/2tz1933146.html

相关文章: