首页 > Vue >

elementUI权限树组件改成左边勾选到右边列表展现

时间: 作者:admin 浏览:

使用element-ui的时间不短了,它的大部分功能都是很好用的,基本囊括了大部分常见的使用场景组件,最近项目上需要用到权限树这一块,但是element-ui的<el-tree>只是能展现和勾选,项目中要求将勾选的在右侧显示,于是在<el-tree>的基础上改造了一下,做成公用的组件,以便调用和扩展,先来图片欣赏下:

不多说,直接上代码:

//html部分
<template>
    <div class="operation-tree-box" :style="boxStyle" :class="boxClass">
        <el-form ref="operationForm" :model="userOperationForm" :rules="rules" label-width="0" class="operation-form">
            <el-form-item label="" prop="defaultCheckedKeysArr">
                <el-col :span="treeColspanNum">
                    <div class="tree-title" v-if="showTreeTitle"><slot :row="treeTitle" name="treeTitle">{{treeTitle}}</slot></div>
                    <div class="tree-box" :style="treeStyle">
                        <el-tree
                            ref="tree"
                            class="tree-content"
                            v-loading="vloading"
                            :default-expand-all="expandAll"
                            :show-checkbox="showCheckbox"
                            :node-key="nodeKey"
                            :data="treeData"
                            :default-checked-keys="userOperationForm.defaultCheckedKeysArr"
                            :props="props"
                            :render-content="renderContents"
                            @check="handleCheck"
                        ></el-tree>
                    </div>
                </el-col>
                <el-col :span="hadChoseColspanNum" v-if="showHadChose">
                    <div class="had-chose-title" v-if="showHadChoseTitle">
                        <slot :row="hadChoseTitle" name="hadChoseTitle">{{hadChoseTitle}}</slot></div>
                    <div class="had-chose-box" :style="hadChoseStyle">
                        <ol class="had-chose-content">
                            <li v-for="item in hadChoseData" :key="item" >{{item.name}}</li>
                        </ol>
                    </div>
                </el-col>
            </el-form-item>
        </el-form>
    </div>
</template>
//js部分
import {Tree} from 'element-ui'
export default {
    name:"operation-tree",
    mixins:[Tree],
    data(){
        return {
            vloading:false,
            userOperationForm:{
                defaultCheckedKeysArr:[]
            },
            rules:{
                defaultCheckedKeysArr:[
                    {
                        validator:this.validator
                    }
                ]
            },
            treeData:[],
            hadChoseData:[]
        }
    },
    props:{
        outData:{
            type:Array,
            default:()=>{
                return []
            }
        },
        originOperationIdArr:{
            type:Array,
            default:()=>{
                return []
            }
        },
        renderContents:{
            type:Function,
            default:(h, { node, data, store })=>{
                if(node.level == 1){
                    if(node.expanded){
                        return (
                            <span class="custom-tree-node">
                                <i class="el-icon-folder-opened"></i>
                                <span class="label-item">{node.label}</span>
                            </span>
                        );
                    }else{
                        return (
                            <span class="custom-tree-node">
                                <i class="el-icon-folder"></i>
                                <span class="label-item">{node.label}</span>
                            </span>
                        );
                    }
                }else if(node.level == 2){
                    return (
                        <span class="custom-tree-node">
                            <i class="el-icon-notebook-1"></i>
                            <span class="label-item">{node.label}</span>
                        </span>
                    );
                }else{
                    return (
                        <span class="custom-tree-node">
                            <i class="el-icon-document"></i>
                            <span class="label-item">{node.label}</span>
                        </span>
                    );
                }
            }
        },
        expandAll:{
            type:Boolean,
            default:true
        },
        showCheckbox:{
            type:Boolean,
            default:true
        },
        props:{
            type:Object,
            default:()=>{
                return {
                    label:'name'
                }
            }
        },
        loading:{
            type:Boolean,
            default:false
        },
        nodeKey:{
            type:String,
            default:'id'
        },
        validator:{
            type:Function,
            default:(rule,value,callback)=>{
                if(value && value.length == 0){
                    return callback(new Error("至少选择一个权限!"))
                }else{
                    return callback();
                }
            }
        },
        treeColspanNum:{
            type:Number,
            default:12
        },
        hadChoseColspanNum:{
            type:Number,
            default:12
        },
        boxStyle:{
            type:Object,
            default:()=>{
                return {
                    width:'100%'
                }
            }
        },
        treeStyle:{
            type:Object,
            default:()=>{
                return {}
            }
        },
        hadChoseStyle:{
            type:Object,
            default:()=>{
                return {}
            }
        },
        boxClass:{
            type:String,
            default:''
        },
        showHadChose:{
            type:Boolean,
            default:true
        },
        showTreeTitle:{
            type:Boolean,
            default:true
        },
        showHadChoseTitle:{
            type:Boolean,
            default:true
        },
        treeTitle:{
            type:String,
            default:'所有权限'
        },
        hadChoseTitle:{
            type:String,
            default:'已选权限'
        },
        allDisabled:{
            type:Boolean,
            default:false
        },
        operationThen:{
            type:Function,
            default:()=>{

            }
        }

    },
    watch:{
        loading(val){
            this.vloading = val;
        }
    },
    mounted(){
        if(this.outData && this.outData.length){
            this.setData(this.outData,this.originOperationIdArr);
        }else{
            this.loadRole(this.originOperationIdArr);
        }
    },
    methods:{
        deepForEachDisabled(rows){
            rows.forEach((item,i)=>{
                item.disabled = true;
                if(item.children && item.children.length){
                    this.deepForEachDisabled(item.children);
                }
            })
        },
        setData(treeData,originOperationIdArr){
            this.treeData = treeData;
            this.userOperationForm.defaultCheckedKeysArr = originOperationIdArr;
            if(this.showHadChose){
                this.setHadChose();
            }
            if(this.allDisabled){
                this.deepForEachDisabled(treeData);
            }
            this.$emit('operationThen',this.outData || treeData);
            this.vloading = false;
        },
        loadRole(originOperationIdArr){
            this.vloading = true;
            this.$axios.get('/system/operation',{
                params:{}
            }).then(res=>{
                this.$common.thenFactory({
                    res:res,
                    t:this
                }).then((res)=>{
                    this.setData(res.data.content,originOperationIdArr);
                })
            }).catch(err=>{
                this.$common.systemCatch(err,this)
            })
        },
        setHadChose(){
            this.$nextTick(()=>{
                let tempChose = [];
                this.$refs.tree.getCheckedNodes().forEach((item)=>{
                    if(item.leaf){
                        tempChose.push(item);
                    }
                })
                this.hadChoseData = tempChose;
            })
        },
        handleCheck(currentNode,allCheckedNode){
            let keys=[];
            this.hadChoseData=[];
            allCheckedNode.checkedNodes.forEach((item)=>{
                keys.push(item.id);
                if(item.leaf){
                    this.hadChoseData.push(item);
                }
            })
            this.userOperationForm.defaultCheckedKeysArr = keys;
            this.$refs.operationForm.validateField('defaultCheckedKeysArr');
            this.$emit("check",currentNode,allCheckedNode);
        }
    }
}
//css部分

.operation-tree-box{
    text-align: center;
}
.operation-tree-box .tree-box{
    height:398px;
    border:1px solid #DCDFE6;
    overflow-y:auto;
    overflow-x:hidden;
}
.operation-tree-box .tree-content{
    padding:6px;
}
.operation-tree-box .operation-form{
    display:inline-block;
    width:100%;
    min-width:25rem;
    max-width:80rem;
}
.operation-tree-box /deep/ .el-tree-node .el-tree-node__content:hover,
.operation-tree-box /deep/ .el-tree-node .el-tree-node__content:active,
.operation-tree-box /deep/ .el-tree-node .el-tree-node__content:visited,
.operation-tree-box /deep/ .el-tree-node .el-tree-node__content:focus{
    background-color:#FFF;
}
.operation-tree-box /deep/ .el-tree-node__expand-icon{
    color:#000;
}
.operation-tree-box /deep/ .el-tree-node__expand-icon.is-leaf{
    color:transparent;
}
.operation-tree-box /deep/ .custom-tree-node .label-item{
    padding-left:5px;
}
.operation-tree-box .had-chose-box{
    height:398px;
    border:1px solid #DCDFE6;
    border-left:none;
    overflow-y:auto;
    overflow-x:hidden;
}
.operation-tree-box .tree-title{
    font-weight:bold;
    border:1px solid #DCDFE6;
    border-bottom:none;
}
.operation-tree-box .had-chose-title{
    font-weight:bold;
    border:1px solid #DCDFE6;
    border-bottom:none;
    border-left:none;
}
.operation-tree-box .had-chose-content{
    text-align: left;
}
.operation-tree-box .had-chose-content >li{
    height:1.625rem;
    line-height: 1.625rem;
}
//引用 

<template>
    <v-operationtree
        ref="operationTree"
        :originOperationIdArr="originOperationIdArr"
        :hadChoseTitle="hadChoseTitle"
        @check="checkOperation"
    ></v-operationtree>
</template>
import vOperationtree from './operation-tree'

注意事项:

1、loadRole方法的请改成你自己的默认权限树请求链接,本组件支持外传数据进来的,可以在引用的时候传值给outData:[{},{},…]这样的形式即可;

2、其他参数多是沿用原来<el-tree>的参数,对照官网参数即可扩展,其中originOperationIdArr是默认选中的数据[1212,11212,21212]数组;allDisabled意思是所有checkbox都禁用,在仅支持查看的时候用到;

3、组件的具名slot插槽都是可以直接替换用的;

4、this.$common.thenFactory是小编自己的公共方法,你们只要拿到数据给setData()方法就可以了;

5、至于mixins混入Tree这个可以不要的,混入可以也有延迟,小编是经常执行了Tree里的方法拿不到值的,比如混入之后直接this.getCheckedNodes()去拿已选中的所有节点数组,经常拿到是空,方法调用没报错,但是取不到值,估计组件里面已经用过$nextTick;还是用ref稳妥点,使用过程自己感受下;

6、小编更愿意给demo的,可vue组件运行需要安装node环境,这样就很为难了,不像以前只要个html静态文件就可以了,慢慢看吧;

微信公众号
微信公众号:
  • 前端全栈之路(微信群)
前端QQ交流群
前端QQ交流群:
  • 794324979
  • 734802480(已满)

更多文章

栏目文章


Copyright © 2014-2023 seozhijia.net 版权所有-粤ICP备13087626号-4