zoukankan      html  css  js  c++  java
  • vue+element树形结构右键菜单

    环境:vue-admin-template   vue 2.6.10 element-ui 2.7.0

    1、自定义组件,文件位置:src/components/mentContext

    <template>
        <!-- @mousedown.stop  阻止冒泡事件-->
        <!-- @contextmenu.prevent 阻止右键的默认事件 -->
        <div id="dropMenu"
             :style="style"
             style="display: block;"
             v-show="show"
             @mousedown.stop
             @contextmenu.prevent>
            <slot></slot>
        </div>
    </template>
    <script>
        export default {
            name:"menuContext",
            data() {
                return {
                    triggerShowFn: () => {
                    },
                    triggerHideFn: () => {
                    },
                    x: null,
                    y: null,
                    style: {},
                    binded: false
                }
            },
            props: {
                target: null,
                show: Boolean
            },
            mounted() {
                this.bindEvents()
            },
            watch: {
                show(show) {
                    if (show) {
                        this.bindHideEvents()
                    } else {
                        this.unbindHideEvents()
                    }
                },
                target(target) {
                    this.bindEvents()
                }
            },
            methods: {
                // 初始化事件
                bindEvents() {
                    this.$nextTick(() => {
                        var that = this
                        if (!this.target || this.binded) return
                        this.triggerShowFn = this.contextMenuHandler.bind(this)
                        this.target.addEventListener('contextmenu', this.triggerShowFn)
                        //this.binded = true
                    })
                },
                // 取消绑定事件
                unbindEvents() {
                    if (!this.target) return
                    this.target.removeEventListener('contextmenu', this.triggerShowFn)
                },
                // 绑定隐藏菜单事件
                bindHideEvents() {
                    this.triggerHideFn = this.clickDocumentHandler.bind(this)
                    document.addEventListener('mousedown', this.triggerHideFn)
                    document.addEventListener('mousewheel', this.triggerHideFn)
                },
                // 取消绑定隐藏菜单事件
                unbindHideEvents() {
                    document.removeEventListener('mousedown', this.triggerHideFn)
                    document.removeEventListener('mousewheel', this.triggerHideFn)
                },
                // 鼠标按压事件处理器
                clickDocumentHandler(e) {
                    this.$emit('update:show', false) //隐藏
                },
                // 右键事件事件处理
                contextMenuHandler(e) {
                    e.target.click()//这个是因为我需要获取tree节点的数据,所以我通过点击事件去获取数据
                    this.x = e.clientX - 240
                    this.y = e.clientY - 110
                    this.layout()
                    this.$emit('update:show', true)  //显示
                    e.preventDefault()
                    e.stopPropagation()
    
                    this.$emit('targetElement', e.target) //我还要获取右键的DOM元素进行操作
                },
                // 布局
                layout() {
                    this.style = {
                        left: this.x + 'px',
                        top: this.y + 'px'
                    }
                }
            }
        }
    </script>
    <style lang="scss">
        #dropMenu {
            position: absolute;
            margin: 0;
            padding: 0;
             80px;
            height: auto;
            border: 1px solid #ccc;
            border-radius: 4px;
    
            ul {
                list-style: none;
                margin: 0;
                padding: 0;
    
                li {
                     100%;
                    text-align: center;
                    height: 30px;
                    line-height: 30px;
                    background: #eee;
                    margin-bottom: 1px;
                    cursor: pointer;
                }
            }
        }
    </style>

    2、调用,src/views 自己的项目目录里

    <template>
        <div class="app-container">
            <h2>当前目录:</h2>
            <h4>{{ current_path }}</h4>
    
            <el-input
                    placeholder="输入关键字进行过滤"
                    v-model="filterText">
            </el-input>
    
            <!-- 树形结构 -->
            <el-tree
                    id="modelTree"
                    ref="tree"
                    :data="treedata"
                    :props="defaultProps"
                    class="filter-tree"
                    accordion
                    node-key="id"
                    :filter-node-method="filterNode"
            >
            </el-tree>
    
            <!-- 右键菜单 -->
            <menu-context
                    :target="contextMenuTarget"
                    :show="isShowDrop"
                    @update:show="(show) => isShowDrop = show"
                    @targetElement="getTargetElement">
                <ul>        <!--按需展示按钮-->
                    <li v-show="isShowDelete" @click="deleteOne">删除</li>
                    <li v-show="isShowAdd" @click="add">添加</li>
                    <li v-show="isShowEdit" @click="editNode">编辑</li>
                    <li v-show="isShowLink" @click="linkModels">关联</li>
                    <li v-show="isShowMove" @click="move">转移</li>
                </ul>
            </menu-context>
    
            <el-dialog
                    :title="textMap[dialogStatus]"
                    :visible.sync="dialogFormVisible"
                    :close-on-click-modal="false"
                    width="70%"
                    top="5vh"
                    @open="resetForm('dataForm')"
            >
                <el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="100px">
                    <el-form-item v-if="false" label="ID" prop="id">
                        <el-input v-model="temp.id"/>
                    </el-form-item>
                    <el-form-item label="脚本路径" prop="path">
                        <p>{{ temp.path }}</p>
                    </el-form-item>
                    <el-form-item label="脚本名称" prop="name">
                        <el-input v-model="temp.name" placeholder="请输入具有辨识性的名称"/>
                    </el-form-item>
                    <el-form-item label="脚本内容" prop="filebody">
                        <codemirror v-model="temp.filebody" :options="cmOptions"/>
                    </el-form-item>
                </el-form>
                <div slot="footer" class="dialog-footer">
    
                    <el-button @click="dialogFormVisible = false">
                        取消
                    </el-button>
                    <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()">
                        提交
                    </el-button>
                </div>
            </el-dialog>
        </div>
    </template>
    
    <script>
        import {Message} from 'element-ui'
        import * as LocalScriptsApi from '@/api/hostmanage'
        // 在线代码编辑器
        import {codemirror} from 'vue-codemirror'
        import 'codemirror/lib/codemirror.css'
        import 'codemirror/mode/yaml/yaml.js'
        import 'codemirror/theme/monokai.css'
        import request from "@/utils/request";
        import store from "@/store";
        import menuContext from '@/components/menuContext'
    
        let id = 1000;
        export default {
            components: {
                menuContext,
                codemirror
            },
            data() {
                return {
                    // 树形节点参数
                    filterText: '', // 过滤内容
                    treedata: [],  // 属性节点内容
                    current_path: '',
                    defaultProps: {  //节点内容的key
                        children: 'children',
                        label: 'label'
                    },
                    // 右键菜单参数
                    isShowDrop: false, //右键菜单的是否显示
                    contextMenuTarget: null, //右键菜单的DOM对象
                    thisformdata: {}, //右键菜单的点击的节点对象
                    targetElement: {}, //右键点击的目标对象
                    isShowDelete: true, //是否显示菜单中的删除按钮
                    isShowEdit: true, //是否显示菜单中的 编辑按钮
                    isShowAdd: true, //是否显示菜单中的 添加按钮
                    isShowMove: true, //是否显示菜单中的 转移按钮
                    isShowLink: true, //是否显示菜单中的 关联按钮
    
                    // 以下为模态框的参数
                    temp: {
                        id: undefined,
                        name: '',
                        filebody: '',
                        path:''
                    },
                    cmOptions: { // codemirror options
                        tabSize: 2,
                        mode: 'text/x-yaml',
                        theme: 'monokai',
                        lineNumbers: true,
                        line: true
                    },
                    dialogFormVisible: false,
                    dialogStatus: '',
                    textMap: {
                        update: '修改脚本',
                        create: '新增脚本'
                    },
                    rules: {
                        name: [{required: true, message: '请输入脚本名称', trigger: 'blur'}],
                        filebody: [{required: true, message: '请输入脚本内容', trigger: 'blur'}],
                    },
                };
            },
            created() {
                this.fetchTreeData()
            },
            mounted() {
                this.isShowDrop = false;
                //dom加载完,进行目标dom的设置,直接在data中赋值,会找不到dom
                this.contextMenuTarget = document.querySelector('#modelTree')
            },
            watch: {
                filterText(val) {
                    this.$refs.tree.filter(val);
                },
            },
            methods: {
                filterNode(value, data) { // 节点过滤
                    if (!value) return true;
                    return data.label.indexOf(value) !== -1;
                },
                fetchTreeData() { // 空间树数据
                    LocalScriptsApi.queryscripts().then(resp => {
                        if (resp.status === false) {
                            Message({
                                message: response.message || '后端无返回说明信息',
                                type: 'error',
                                duration: 5 * 1000
                            })
                        } else {
                            this.treedata = resp.data.info
                            this.current_path = resp.data.current_path
                        }
    
                    })
                },
                getTargetElement(v) {
                    this.targetElement = v
                },
                deleteOne() {
                    var that = this
                    var nodeIds = [this.thisformdata.nodeId]
                    this.$confirm('此操作将删除该节点及其子节点, 是否继续?', '提示', {
                        confirmButtonText: '确定',
                        cancelButtonText: '取消',
                        type: 'warning',
                        center: true
                    })
                            .then(() => {
                                deleteTreeNode(that.spaceTreeId, nodeIds).then(function (res) {
                                    console.log('deleteTreeNode', res)
                                    if (res.success) {
                                        that.$message('删除成功!')
                                        that.refreshSpaceTree()
                                    }
                                })
                            })
                            .catch(() => {
                            })
                },
                add() {
                    this.append(this.thisformdata)
                    this.isShowDrop = false
                },
                editNode() {
                    var data = this.thisformdata
                    var str = "<input type='text' name='label' value='" + data.name + "'>"
                    var e = window.event
                    var text = this.targetElement
                    text.innerHTML = str
                    this.isShowDrop = false
                    text.lastChild.onblur = function () {
                        data.name = text.lastChild.value
                        text.innerHTML = text.lastChild.value
                        var that = this
                        var space = {
                            nodeId: data.nodeId,
                            orgnazitionalTreeID: data.orgnazitionalTreeID,
                            parentNodeId: data.parentNodeId,
                            name: data.name,
                            nodeType: data.nodeType
                        }
                        //发送请求修改内容=>?有问题明天要修改
                        modifyTreeNode(data.orgnazitionalTreeID, space).then(function (res) {
                            console.log('modifyTreeNode', res)
                        })
                    }
                },
                move() {
                    if (this.thisformdata.nodeType == 0) {
                        this.$refs.modelLinkSpace.Open([this.thisformdata])
                    }
                    this.isShowDrop = false
                },
                linkModels() {
                    this.linkModel({}, this.thisformdata)
                },
                handleNodeClick(data) {
                    console.log('handleNodeClick', data)
                    // !核心 : 节点数据被获得
                    this.thisformdata = data
                    //按需展示不同的按钮
                    if (data.nodeType == 1 && !data.children) {
                        this.isShowAdd = true
                        this.isShowLink = true
                        this.isShowMove = true
                    } else if (data.nodeType == 0) {
                        this.isShowAdd = false
                        this.isShowLink = false
                        this.isShowMove = true
                    } else if (data.nodeType == 1 && data.children && data.children[0].nodeType == 0) {
                        this.isShowAdd = false
                        this.isShowLink = true
                        this.isShowMove = true
                    } else if (data.nodeType == 1 && data.children && data.children[0].nodeType == 1) {
                        this.isShowAdd = true
                        this.isShowLink = false
                        this.isShowMove = false
                    }
                },
                // 清空表单数据
                resetForm(formName) {
                    this.$nextTick(() => {
                        this.$refs[formName].resetFields()
                    })
                },
                append(data) {
                    console.log(data)
                    this.dialogStatus = 'create'
                    this.dialogFormVisible = true
                    // 自己定义逻辑
                },
            }
        };
    
    </script>
    
    <style lang="scss">
    
    </style>

     参考资料:https://www.cnblogs.com/xuqp/p/11117636.html

  • 相关阅读:
    CSS复合选择器
    模块之shutil模块模块详解
    模块之sys模块详解
    模块之os模块详解
    map遍历
    java完美处理表情符
    死磕设计模式—建造者模式
    Java String getChars()方法
    Java知识系统回顾整理01基础06数组05复制数组
    Java知识系统回顾整理01基础06数组04增强型for循环
  • 原文地址:https://www.cnblogs.com/cherylgi/p/13307037.html
Copyright © 2011-2022 走看看