美文网首页
vue 自定义右键样式

vue 自定义右键样式

作者: 水君子Z | 来源:发表于2019-09-26 12:19 被阅读0次

    前言

    最近用python写了个小说程序的api,想着用vue做个系统管理数据,脑子里出现的是这个画面:
    image
    但是这种样式的管理后台已经做了太多了,已经审美疲劳,后面又想了一种类操作系统的UI界面:
    image
    主要是靠双击右键来操作,可操作多个模态框,跟操作windows类似,接下来在里面拆出一个功能块来写一篇文章,就是```自定义系统默认的右键。
    自定义右键操作有五个步骤:
    1. 阻止默认右键。
    2. 获取当前右键点击时的x/y坐标,及id。
    3. 自定义右键菜单样式及内容,定位在指定的位置后显示。
    4. 返回对应点击目录的事件如:查看、删除、编辑。
    5. 在任何地方点击左键时隐藏右键菜单。
    关键方法:
    @contextmenu.prevent
    

    这个是vue内置的,点击右键(阻止默认右键的默认行为)的一个回调方法,他返回了一大串东西这里我用到的是这两个(用于定位显示菜单的x,y位置)

    但是这里会出现一个问题:

    操作1:
    
    <!--template-->
    <ul>
        <li class="role_list" 
            v-for="(item,index) in role" 
            :key="index"
            @contextmenu.prevent="rightClick">
            <img :src="item.head_portrait" alt="">
            <p>{{item.name}}</p>
        </li>
    </ul>
    
    <!--script-->
    methods:{
        rightClick(e){
            <!--这里只能拿到坐标,但拿不到点击对应的id-->
            console.log(e)
        }
    }
    
    
    操作2:
    <!--template-->
    <ul>
        <li class="role_list" 
            v-for="(item,index) in role" 
            :key="index"
            @contextmenu.prevent="rightClick(item.id)">
            <img :src="item.head_portrait" alt="">
            <p>{{item.name}}</p>
        </li>
    </ul>
    
    <!--script-->
    methods:{
        rightClick(id){
            <!--这里只能拿到id,但拿不到点击对应的坐标-->
            console.log(id)
        }
    }
    
    解决方法:

    x_indexy_index 是储存在data中的,用于定位模态框位置。
    ctrlId 用于给接口处理的依据
    showMenu 用于判断是否显示右键菜单

    <!--template-->
    <ul>
        <li class="role_list" 
            v-for="(item,index) in role" 
            :key="index"
            @contextmenu.prevent="(e)=>{
                x_index = e.layerX;
                y_index = e.layerY;
                ctrlId = item.id;
                showMenu = true;
            }">
            <img :src="item.head_portrait" alt="">
            <p>{{item.name}}</p>
        </li>
    </ul>
    

    需要的参数(x,y,id)都具备了,因为右键操作很多地方都用到了,所以封装成了一个组件

    right_menu.vue 组件代码

    参数名 注释
    x x坐标
    y y坐标
    showMenu 显示状态
    <template>
        <div v-if="show"
             class="menu_style" 
             :style="{top:y+'px',left:x+'px'}">
            <ul>
                <!-- 分别传递事件给父元素调用 -->
                <li @click="()=>{$emit('open')}">打开</li>
                <li @click="()=>{$emit('update')}">编辑</li>
                <li @click="()=>{$emit('del')}">删除</li>
            </ul>
        </div>
    </template>
    <script>
        export default{
            name:'right_menu',
            props:{
                x:{
                    type:[Number],
                    default:0
                },
                y:{
                    type:[Number],
                    default:0
                },
                showMenu:{
                    type:[Boolean],
                    default:false
                }
            },
            data(){
                return {
                    show:false,
                }
            },
            methods:{
                // 点击别处时隐藏目录,并传递一个关闭事件
                closeMenu(e){
                    this.show = false;
                    this.$emit("close",false)
                },
            },
            mounted(){
                // 监听body上的点击
                document.querySelector("body").addEventListener("click",this.closeMenu)
            },
            beforeDestroy(){
                // 移除监听
                document.querySelector("body").removeEventListener("click",this.closeMenu)
            },
            watch:{
                // 监听,保持显示状态与父元素一致
                showMenu(val){
                    this.show = val;
                }
            },
        }
    </script>
    <style scoped>
        .menu_style{
            position: absolute;
            width: 150px;
            background-color: #fff;
            border-radius: 2px;
            box-shadow: 2px 2px 14px #d0d0d0;
        }
        .menu_style>ul>li{
            text-indent: 25px;
            height: 38px;
            line-height: 38px;
            border-bottom: 1px dashed #f0f0f0;
            cursor: pointer;
        }
        .menu_style>ul>li:hover{
            background: #E0EEFF;
        }
    </style>
    
    组件使用
    <template>
        <div class="modal_data_box">
            <ul>
                <li class="role_list" 
                    v-for="(item,index) in role" 
                    :key="index"
                    @contextmenu.prevent="(e)=>{
                        x_index = e.layerX;
                        y_index = e.layerY;
                        ctrlId = item.id;
                        showMenu = true;
                    }">
                    <img :src="item.head_portrait" alt="">
                    <p>{{item.name}}</p>
                </li>
            </ul>
        <!--组件-->
        <right-menu :x="x_index"
                    :y="y_index" 
                    :showMenu="showMenu"
                    @close="closeMenu"
                    @open="openDetail"
                    @del="delAttr"
                    @update="updateArr">
        </right-menu>
        </div>
    </template>
    <script>
        // 导入组件
        import rightMenu from '../module/right_menu.vue';
        export default{
            name:"roleModal",
            components:{rightMenu},
            data(){
                return {
                    x_index:0,
                    y_index:0,
                    ctrlId:'',
                    showMenu:false,
                    role:[],
                }
            },
            methods:{
                //关闭回调  
                closeMenu(state){
                    console.log('关闭')
                    this.showMenu = state;
                },
                //打开详情回调            
                openDetail(){
                    console.log('编辑')
                },
                //删除回调          
                delAttr(){
                    console.log('删除')
                },
                //编辑回调          
                updateArr(){
                    console.log('编辑')
                },
            }
        }
    </script>
    
    其余文章:

    css图片以最长边显示

    flask多图片储存优化

    flask 实现token机制

    相关文章

      网友评论

          本文标题:vue 自定义右键样式

          本文链接:https://www.haomeiwen.com/subject/ehgguctx.html