树形结构穿梭框_html5treetable

树形结构穿梭框_html5treetable最近遇到个需求,穿梭框中的内容是树形结构的数据。查看elementUI的transfer组件是不支持树形结构的数据,也就不能直接使用了。但是el-tree组件支持啊,那如果让tree组件和transfer组件结合一下岂不完美🤔。 clone一份element的源码,找到pac…

最近遇到个需求,穿梭框中的内容是树形结构的数据。查看elementUI的transfer组件是不支持树形结构的数据,也就不能直接使用了。但是el-tree组件支持啊,那如果让tree组件和transfer组件结合一下岂不完美🤔。

准备

clone一份element的源码,找到package/tansfer/src文件夹,里面的vue文件就是我们的目标。复制一份出来到自己的项目(同时复制mixins里的emitter.jsmigrating.js),接下来就对它进行改造。

|-- components
|   |-- mixins
|   |   |-- emitter.js
|   |   |-- migraing.js
|   |-- main.vue
|   |-- transfer-panel.vue

使用

使用之前先对main.vuetransfer-panel.vue两个文件进行简单的修改。删除locale相关代码。emitter.jsmigrating.js因为路径变化需要重新引入。然后在其它组件中引入main.vue就可以使用啦(和直接使用el-transfer是一样的)。

<i-el-transfer v-model="value" :data="data"></i-el-transfer>

...

import iElTransfer from '../components/main'

export default {
    name: 'home',
    components: {
        iElTransfer
    },
    data () {
        return {
            data: [
                { key: 1, label: '备选项1', disabled: false },
                { key: 2, label: '备选项2', disabled: false }
                ...
            ]
        }
    }
    ...
}

image

改造

将原来的单层结构转换成树形结构,我们有现成的el-tree使用,所以将原来显示内容的区域换成el-tree组件看看。

# transfer-panel.vue
...
<el-checkbox-group
    v-model="checked"
    v-show="!hasNoMatch && data.length > 0"
    :class="{ 'is-filterable': filterable }"
    class="el-transfer-panel__list">
    <el-checkbox
        class="el-transfer-panel__item"
        :label="item[keyProp]"
        :disabled="item[disabledProp]"
        :key="item[keyProp]"
        v-for="item in filteredData">
        <option-content :option="item"></option-content>
    </el-checkbox>
</el-checkbox-group>
...

先不管那么多,直接替换成el-tree

...
<div v-show="data.length > 0"
    :class="{ 'is-filterable': filterable }"
    class="el-transfer-panel__list">

    <el-tree ref="tree" :data="filteredData"
        :node-key="keyProp"
        show-checkbox
        default-expand-all
        :default-checked-keys="checked">
    </el-tree> </div>
...

data变为树形结构,回过来看页面

image

是我们像要的结果,这时候虽然变成了我们想要的树形结构,但是操作一下就能发现问题。继续看代码。

sourceData() {
    return this.data.filter(item => this.value.indexOf(item[this.props.key]) === -1);
},

targetData() {
    if (this.targetOrder === 'original') {
        return this.data.filter(item => this.value.indexOf(item[this.props.key]) > -1);
    } else {
        return this.value.reduce((arr, cur) => {
            const val = this.dataObj[cur];
            if (val) {
                arr.push(val);
            }
        return arr;
      }, []);
    }
},

sourceDatatargetData分别用来展示左右两侧的数据,this.value是使用组件时通过v-model绑定的数据。这里通过this.value筛选出左右两边的数据。那我们就在这里做一下修改:

sourceData () {
    const data = deepCopy(this.data)

    // 有children继续筛选
    const filterData = (list) => {
        return list.filter(item => {
            if (item[this.props.children] && item[this.props.children].length > 0) {
                item[this.props.children] = filterData(item.children)
            }
            return this.value.indexOf(item[this.props.key]) === -1
        })
    }

    return filterData(data)
},

targetData () {
    const data = deepCopy(this.data)

    const filterData = (list) => {
        const res = []
        list.forEach(item => {
            if (this.value.indexOf(item[this.props.key]) > -1) {
                res.push(item)
            }

            if (item[this.props.children] && item[this.props.children].length > 0) {
                const result = filterData(item[this.props.children])
                if (result.length > 0) {
                    item[this.props.children] = result
                    const find = res.find(i => i.key === item.key)

                    // res 中没有找到 item,需将 item 加入 res。
                    // 避免当选中子元素,父元素未选中的时候出现问题
                    if (find === undefined) {
                        res.push(item)
                    }
                }
            }
        })
        return res
    }

    return filterData(data)
},

我这里希望添加到右边的数据和左边的数据保持同样的结构,所以删除了targetOrder选项。我们试着改变v-model绑定的值来看下效果。

image

有那感觉了,但是现在向左向右添加的功能还是不行。下面就修改这部分的功能。找到addToRight函数,该函数筛选出用户左侧选中要添加到右侧的数据和已经存在右侧的数据,并通过$emit()修改this.value的值。

addToRight () {
    let currentValue = this.value.slice()
    const itemsToBeMoved = []
    const findSelectkey = (list) => {
        const key = this.props.key
        const itemsToBeMoved = []

        list.forEach(item => {
            const itemKey = item[key]
            if (
                this.leftChecked.indexOf(itemKey) > -1 &&
                this.value.indexOf(itemKey) === -1
            ) {
                itemsToBeMoved.push(itemKey)
            }

            if (item[this.props.children] && item[this.props.children].length > 0) {
                itemsToBeMoved.push(...findSelectkey(item[this.props.children]))
            }
        })
        return itemsToBeMoved
    }

    itemsToBeMoved.push(...findSelectkey(this.data))

    currentValue = currentValue.concat(itemsToBeMoved)

    this.$emit('input', currentValue)
    this.$emit('change', currentValue, 'right', this.leftChecked)
},

其实思路都是一样的,如果存在children就继续查找下层数据。接着修改addToLeft函数。

addToLeft () {
    let currentValue = this.value.slice()
    const list = this.rightChecked.concat(this.rightFalfChecked)
    list.forEach(item => {
        const index = currentValue.indexOf(item)
        if (index > -1) {
            currentValue.splice(index, 1)
        }
    })
    this.$emit('input', currentValue)
    this.$emit('change', currentValue, 'left', this.rightChecked)
},

这里我想的是如果元素的子元素没有被全选,那么该元素不是选中状态,所以要从右侧删除该元素的key。这里新加了一个rightFalfChecked用来表示右侧半选状态的数据。

上面对main.vue文件的修改基本就算完了。我们发现还需要获取到rightCheckedleftCheckedrightFalfChecke的值。修改transfer-panel.vue文件来获取它们。el-tree组件有个check事件,通过它我们可以获取当前el-tree哪些被选中了。

check:当复选框被点击的时候触发;共两个参数,依次为:传递给 data 属性的数组中该节点所对应的对象、树目前的选中状态对象,包含 checkedNodes、checkedKeys、halfCheckedNodes、halfCheckedKeys 四个属性

<el-tree ref="tree" :data="filteredData"
    :node-key="keyProp"
    show-checkbox
    default-expand-all
    :default-checked-keys="checked"
    @check="handleCheck">
</el-tree>

...
watch: {
    checked (val, oldVal) {
        this.updateAllChecked()
        if (this.checkChangeByUser) {
            const movedKeys = val.concat(oldVal)
                .filter(v => val.indexOf(v) === -1 || oldVal.indexOf(v) === -1)
            this.$emit('checked-change', val, movedKeys, this.halfChecked)
        } else {
            this.$emit('checked-change', val)
            this.checkChangeByUser = true
        }
    }
}

...

handleCheck (cur, checkedInfo) {
    const { checkedKeys, halfCheckedKeys } = checkedInfo
    this.checked = checkedKeys
    this.halfChecked = halfCheckedKeys
}

总结

到这里基本功能实现都已经完成了,但是还有一些细节问题,比如全选、筛选等,这里就不再描述。相比原来的transfer组件,这里去掉了targetOrderformat属性,其它的则做了保留或修改。希望这篇文章能帮到您,您可以在下面的链接查看完整代码。欢迎交流🎉️。

Github:链接

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/12918.html

(0)

相关推荐

  • Python字典:快速存储和访问数据的利器

    Python字典:快速存储和访问数据的利器Python是一种高级编程语言,它具有简单易学、易读易写、可扩展等优点,同时也具有优秀的数据结构,其中字典是一种非常常用且便利的数据结构。在本文中,我们将会深入介绍Python字典及其应用,以期帮助读者更好地理解和使用字典。

    2024-01-15
    100
  • 使用Javaweb实现在线调查问卷系统[亲测有效]

    使用Javaweb实现在线调查问卷系统[亲测有效]​  项目编号:BS-PT-014 开发技术: jsp/servlet   前端技术:jquery+layui 开发工具:IDEA/Eclipse 数据库:MYSQL5 功能介绍:      在线调查

    2023-07-16
    125
  • Python字符串分割

    Python字符串分割在编程中,字符串分割是一项非常基础而又重要的操作。Python作为一门强大的编程语言,在字符串分割方面也有其独特的方式和特性。在这篇文章中,我们将会探讨Python中字符串分割的相关知识,并详细介绍它的用法和实际应用。

    2024-05-17
    57
  • centos7 yum方式安装 mysql5.6版本数据库

    centos7 yum方式安装 mysql5.6版本数据库注:出这个版本的安装方式使用因为 centos自带mariadb 其实yum方式安装是可以不用删除mariadb的,安装MySQL会覆盖掉之前已存在的mariadb 1:下载源文件 wget htt…

    2023-03-18
    169
  • 如何在Python中显示中文

    如何在Python中显示中文Python是一种流行的、易学易用的编程语言,许多人使用Python构建自己的应用程序或开发工具。在编程的过程中,有时候需要在Python中显示中文,而不是仅支持英文输出。然而,如果你不了解如何在Python中正确地显示中文,可能会遇到一些奇怪的问题。本文将介绍如何在Python中正确地显示中文。

    2024-07-07
    46
  • 玩转Redis-如何高效访问Redis中的海量数据「建议收藏」

    玩转Redis-如何高效访问Redis中的海量数据「建议收藏」1、前言   Redis以高性能著称,但性能再好,在面对海量数据时,若不正确的使用,也终将会有性能瓶颈,甚至造成服务宕机。 在实际项目中你是否会有以下疑问? 如何访问Redis中的海量数据,却不影响…

    2022-12-19
    144
  • python字符串去除重复字符(python字符串去除重复字符保留左边的)

    python字符串去除重复字符(python字符串去除重复字符保留左边的)普通字符串可以用多种方式编码成unicode字符串,具体要看你究竟选择了哪种编码:

    2023-11-27
    145
  • Python中的软断言和硬断言

    Python中的软断言和硬断言a href=”https://beian.miit.gov.cn/”苏ICP备2023018380号-1/a Copyright www.python100.com .Some Rights Reserved.

    2023-12-10
    116

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注