赞
踩
老规矩----前面文章的步骤创建文件导入js等
封装代码
- <template>
- <!-- target-order="unshift"必须设置,如果不设置的话后台穿的value值得顺序会被data重置 - -->
- <el-transfer
- :id="idDom"
- target-order="unshift"
- style="text-align: left; display: inline-block"
- :model-value="transferData.value"
- filterable
- :filter-method="transferData.menuFilterMethod"
- :left-default-checked="leftChecked"
- :right-default-checked="rightChecked"
- :render-content="renderFunc"
- :titles="titles"
- :button-texts="buttonTexts"
- :format="{
- noChecked: '${total}',
- hasChecked: '${checked}/${total}',
- }"
- :data="dataListT"
- @change="handleChange"
- @left-check-change="leftCheckChange"
- @right-check-change="rightCheckChange"
- >
- <template #default="{ option }">
- <span
- class="item"
- @dragstart="drag($event, option)"
- >{{ option.label || option.title }}</span>
- <!-- {{ option.key }} - -->
- </template>
- <template #left-footer>
- <el-tooltip
- class="box-item"
- effect="dark"
- content="返回左边勾选中的数据"
- placement="top"
- >
- <el-button class="transfer-footer btn-mixins el-button-s" size="small" @click.stop="saveLeft">确定</el-button>
- </el-tooltip>
- </template>
- <template #right-footer>
- <el-tooltip
- class="box-item"
- effect="dark"
- content="返回右边勾选中的数据"
- placement="top"
- >
- <el-button class="transfer-footer btn-mixins el-button-s" size="small" @click.stop="saveRight">确定</el-button>
- </el-tooltip>
- </template>
- </el-transfer>
- </template>
- <script>
- import Sortable from 'sortablejs'
- import { reactive, ref, onMounted } from 'vue'
- const transferData = reactive({
- value: [], // 默认选中的个数索引
- draggingKey: '', // 拖动的数据
- menuFilterMethod(query, item) {
- // return item.menuListdata.indexOf(query) > -1
- const regStr = query.replace(/\*/g, '.*')
- const reg = new RegExp(regStr)
- return reg.test(item.label)
- }
- })
- // 默认数据测试展示
- const generateData = (_) => {
- const data = []
- for (let i = 1; i <= 15; i++) {
- data.push({
- key: i,
- label: `备选项 ${i}`,
- disabled: i % 4 === 0
- })
- }
- return data
- }
- // 数据初始化和拖拽初始化
- const initEffect = (props, ctx) => {
- let dataListT = props.dataList.length ? props.dataList : generateData()
- const init = () => {
- // const transferRef = document.getElementById(props.idDom)
- const transfer = document.getElementById(props.idDom)
- const leftPanel = transfer.getElementsByClassName('el-transfer-panel')[0].getElementsByClassName('el-transfer-panel__body')[0]
- const rightPanel = transfer.getElementsByClassName('el-transfer-panel')[1].getElementsByClassName('el-transfer-panel__body')[0]
- const rightEl = rightPanel.getElementsByClassName('el-transfer-panel__list')[0]
- Sortable.create(rightEl, {
- animation: 100,
- onEnd: (evt) => {
- const { oldIndex, newIndex } = evt
- const temp = transferData.value[oldIndex]
- if (!temp || temp === 'undefined') {
- return
- } // 解决右边最后一项从右边拖左边,有undefined的问题 //这里和网上的有点不一样,网上搜到的结果排序是,当前拖拽的元素和拖拽位置的元素互换位置,但是实际上在使用el-transfer有两个问题 //1.右侧排序value的数组顺序来源于后台穿的数组顺序,实际如果不设置target-order="unshift"的话,展示会按照左侧的数据列顺序展示,导致拖拽排序时顺序乱七八糟 //2.实际拖拽排序看到的效果是当前拖拽元素拖拽到其他地方,其他地方的元素会下移,而不是调换顺序
- // 去除空字符串
- for (var i = 0; i < transferData.value.length; i++) {
- if (
- transferData.value[i] === '' ||
- transferData.value[i] === null ||
- typeof transferData.value[i] === 'undefined'
- ) {
- transferData.value.splice(i, 1)
- i = i - 1
- }
- }
- const arr_temp = [].concat(transferData.value) // 创建一个新的临时数组,用以操作后不变更原数组
- arr_temp.splice(newIndex, 0, arr_temp.splice(oldIndex, 1)[0]) // 在b位置插入从a位置截取的元素
- transferData.value = arr_temp
- ctx.emit('update:call-back', transferData.value)
- }
- })
- const leftEl = leftPanel.getElementsByClassName('el-transfer-panel__list')[0]
- Sortable.create(leftEl, {
- animation: 100,
- onEnd: (evt) => {
- const { oldIndex, newIndex } = evt
- dataListT.splice(newIndex, 0, dataListT.splice(oldIndex, 1)[0])
- // 保存的新的数组用于数据渲染
- const newArray = dataListT.slice(0)
- dataListT = newArray
- }
- })
- leftPanel.ondragover = (ev) => {
- ev.preventDefault()
- }
- leftPanel.ondrop = (ev) => {
- ev.preventDefault()
- const index = transferData.value.indexOf(transferData.draggingKey)
- if (index !== -1) {
- transferData.value.splice(index, 1)
- }
- }
- rightPanel.ondragover = (ev) => {
- ev.preventDefault()
- }
- rightPanel.ondrop = (ev) => {
- ev.preventDefault()
- if (transferData.value.indexOf(transferData.draggingKey) === -1) {
- transferData.value.push(transferData.draggingKey)
- }
- }
- }
- return { init, dataListT }
- }
- // 左边确定按钮 把左边默认展示的传递过去
- const leftBtnEffect = (props, ctx) => {
- const leftDataChecked = ref([])
- leftDataChecked.value = props.leftChecked
- // props.leftChecked.forEach(e => {
- // if (!e.disabled) {
- // leftDataChecked.value.push(e)
- // }
- // })
- const leftCheckChange = (value) => {
- // console.log(value)
- leftDataChecked.value = value
- }
- // console.log(leftDataChecked.value)
- // 左侧确定事件
- const saveLeft = () => {
- ctx.emit('changeTransferLeft', leftDataChecked)
- }
- return { leftDataChecked, leftCheckChange, saveLeft }
- }
- // 右边确定按钮 把右边默认展示的传递过去
- const rightBtnEffect = (props, ctx) => {
- const rightDataChecked = ref([])
- rightDataChecked.value = props.rightChecked
- // props.rightChecked.forEach(e => {
- // if (!e.disabled) {
- // rightDataChecked.value.push(e)
- // }
- // })
- const rightCheckChange = (value) => {
- // console.log(value)
- rightDataChecked.value = value
- }
- // 右侧确定事件
- const saveRight = () => {
- ctx.emit('changeTransferRight', rightDataChecked)
- }
- return { rightDataChecked, rightCheckChange, saveRight }
- }
- export default {
- props: {
- value: {
- type: Array,
- default() {
- return []
- }
- },
- // 按钮文字
- idDom: {
- default() {
- return 'transfer'
- },
- type: String
- },
- // 按钮文字
- buttonTexts: {
- default() {
- return []
- },
- type: Array
- },
- // 数据
- dataList: {
- default() {
- return []
- },
- type: Array
- },
- leftChecked: {
- default() {
- return []
- },
- type: Array
- },
- rightChecked: {
- default() {
- return []
- },
- type: Array
- },
- // 标题
- titles: {
- default() {
- return []
- },
- type: Array
- }
- },
- emits: ['changeTransfer', 'changeTransferLeft', 'changeTransferRight'],
- setup(props, ctx) {
- const { init, dataListT } = initEffect(props, ctx)
- const { leftCheckChange, saveLeft } = leftBtnEffect(props, ctx)
- const { rightCheckChange, saveRight } = rightBtnEffect(props, ctx)
- // 数据加载完之后 再获取对应的id
- onMounted(() => {
- init()
- })
- const renderFunc = (h, option) => {
- return h('span', null, option.label)
- }
- const handleChange = (value, direction, movedKeys) => {
- ctx.emit('changeTransfer', value, direction, movedKeys)
- }
- const drag = (ev, option) => {
- transferData.draggingKey = option.key
- }
- return { transferData, dataListT, handleChange, drag, leftCheckChange, saveLeft, rightCheckChange, saveRight, renderFunc }
- }
- }
- </script>
- <style lang="scss" >
- .el-transfer__buttons {
- .el-button:first-child {
- margin-bottom: 8px;
- }
- }
- </style>
使用
- <template>
- <div>
- <LZTransfer
- v-model="transferData.value"
- :id-dom="transferData.transferId"
- :button-texts="transferData.buttonTexts"
- :left-checked="transferData.leftChecked"
- :left-data-list="transferData.leftDataList"
- :right-checked="transferData.rightChecked"
- :right-data-list="transferData.rightDataList"
- :titles="transferData.titles"
- @changeTransfer="changeTransfer"
- @changeTransferLeft="changeTransferLeft"
- @changeTransferRight="changeTransferRight"
- ></LZTransfer>
- </div>
- <div>
- <span>一个页面有两个穿梭框的展示和数据问题</span>
- <LZTransfer
- v-model="transferData2.value"
- :data-list="transferData2.dataList"
- :id-dom="transferData2.transferId2"
- :button-texts="transferData2.buttonTexts"
- :left-checked="transferData2.leftChecked"
- :right-checked="transferData2.rightChecked"
- :titles="transferData2.titles"
- @changeTransfer="changeTransfer2"
- @changeTransferLeft="changeTransferLeft2"
- @changeTransferRight="changeTransferRight2"
- ></LZTransfer>
- </div>
- </template>
-
- <script>
- import { reactive } from 'vue'
- const transferData = reactive({
- // 默认右移动的数据
- value: [2, 3],
- // 箭头描述
- buttonTexts: ['到左边', '到右边'],
- // 左边默认选中
- leftChecked: [1, 4],
- // 右边默认选中
- rightChecked: [2, 3],
- // 每个穿梭框id
- transferId: 'transferId1',
- titles: ['左边标题', '右边标题'] // 自定义数据 里面必须要要label或者title 才能展示文字
- })
- const transferData2 = reactive({
- value: [],
- // 箭头描述
- buttonTexts: ['到左边2', '到右边2'],
- // 左边默认选中
- leftChecked: [5, 4],
- // 右边默认选中
- rightChecked: [],
- // 每个id
- transferId2: 'transferId2',
- titles: ['左边标题2', '右边标题2'],
- // 自定义数据 里面必须要要label或者title 才能展示文字
- dataList: [
- {
- disabled: false,
- key: 1,
- label: '备选项 11',
- },
- {
- disabled: false,
- key: 2,
- label: '备选项 2',
- },
- {
- disabled: false,
- key: 3,
- label: '备选项 3',
- },
- {
- disabled: false,
- key: 4,
- label: '备选项 4',
- },
- {
- disabled: false,
- key: 5,
- label: '备选项 5',
- },
- {
- disabled: false,
- key: 6,
- label: '备选项 6',
- },
- {
- disabled: false,
- key: 7,
- label: '备选项 7',
- },
- {
- disabled: false,
- key: 8,
- label: '备选项 8',
- },
- {
- disabled: false,
- key: 9,
- label: '备选项 9',
- },
- {
- disabled: false,
- key: 10,
- label: '备选项 10',
- },
- {
- disabled: false,
- key: 11,
- label: '备选项 11',
- },
- ]
- })
-
- export default {
- setup() {
- // 当前移动的数据和方向 移动的key
- const changeTransfer = (value, direction, movedKeys) => {
- console.log(value, direction, movedKeys)
- }
- const changeTransferLeft = (list) => {
- // 这里要通过.value拿到数据
- console.log(list.value)
- }
- const changeTransferRight = (list) => {
- console.log(list.value)
- }
- const changeTransfer2 = (value, direction, movedKeys) => {
- console.log(value, direction, movedKeys)
- }
- const changeTransferLeft2 = (list) => {
- console.log(list.value)
- }
- const changeTransferRight2 = (list) => {
- console.log(list.value)
- }
- return { transferData, transferData2, changeTransfer, changeTransferLeft, changeTransferRight, changeTransfer2, changeTransferLeft2, changeTransferRight2 }
- }
- }
- </script>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。