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;
        width: 80px;
        height: auto;
        border: 1px solid #ccc;
        border-radius: 4px;

        ul {
            list-style: none;
            margin: 0;
            padding: 0;

            li {
                width: 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM