vue实现点击出现操作弹出框的示例


Posted in Javascript onNovember 05, 2020

vue实现点击出现操作弹出框的示例

如上图所示,这次要实现一个点击出现操作弹框的效果;并将这个功能封装成一个函数,便于在项目的多个地方使用。

具体思路是:

封装一个组件,组件保护一个插槽,我们可以根据不同的场景,利用插槽随意在这个弹框里插入任何元素,这个弹框显示时根据我鼠标的点击位置,定位弹窗的位置,并在组件里面监听鼠标抬起事件,触发事件时将弹窗隐藏;

接着在函数中利用createElement和appendChild方法将弹出框创建并插入到页面中;

   本次实现基于vuecli3

接下来,具体实现:

     首先,我们先写一个demo组件

   在点击出现弹出框的元素上把事件对象数据传递一下,以便获取点击时鼠标的数据,以此确定弹出框的位置

// 文件路径参考: src > views > demo> index.vue
<template>
 <div class="demo-wrapper">
  <div class="demo-div">
   <span>更多功能</span>
   <i class="xk-icon xk-ellipsis" @click.stop='showMenu($event)'></i> // 为了获取鼠标位置,这里把事件对象数据传递一下
  </div>
 </div>
</template>

<script lang="ts">
 import { Vue, Component, Prop, Watch} from "vue-property-decorator";
 @Component({

 })
 export default class articleView extends Vue {
  showMenu($event:any){
   // 点击时出现弹出框
  }
 };
</script>

     接着,我们把弹出框里面的组件也写一下

     组件随便命名为ActionList,组件里面把把列表数据及点击事件都基于父组件传递的值而定,由于只是小demo,所以我们传递的menu数据数组只是简单的字符串数组

// 文件路径参考: src > components > ActionList > index.vue<template>
 <ul class="menu-wrapper">
  <li
   class="menu-item"
   v-for="item in menu"
   :key="item"
   @click="handleClick(item)"
  >
   {{ item }}
  </li>
 </ul>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
@Component
export default class ActionList extends Vue {
 @Prop() menu: string[];
 handleClick(str: string) {
  this.$emit('click', str);
 }
}
</script>

    接着,开始着手写弹框组件

  1、弹框组件的显示隐藏用v-show控制,为什么不用v-if ?因为这里我监听了mouseup事件来让弹框隐藏,如果在插槽里的元素绑定事件,比如点击事件,用v-if 的话,点击插槽里的元素时,弹框先消失,插槽里的点击事件就不会生效了。

     2、handleOpen事件里我们根据鼠标点击位置定位弹框位置。

// 文件路径参考: src > components > PublicModel > index.vue<template>
 <div class="dropdown-menu" :style="style" v-show='showModel'>
  <slot></slot>
 </div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
interface IStyle {
 left?: string;
 right?: string;
 top?: string;
 bottom?: string;
}
@Component
export default class PublicModel extends Vue {
 showModel:boolean = false;
 style:IStyle = {};

 // 组件显示时
 handleOpen($event:any){
  const { clientWidth, clientHeight, scrollWidth, scrollHeight } = document.body || document.documentElement;
  const { pageX, pageY, clientX, clientY } = $event;
  let style:IStyle = {} 
  if(clientX > (clientWidth * 2)/3 ){
   style.right = scrollWidth - pageX + 10 + 'px';
  }else{
   style.left = pageX+10+'px'
  }
  if(clientY > (clientHeight * 2) / 3 ){
   style.bottom = scrollHeight - pageY + 10 + 'px';
  }else{
   style.top = pageY + 10 + "px"
  }
  this.style = style;
  this.showModel = true;
  document.addEventListener('mouseup',this.closeModel)
 }

 // 隐藏关闭此组件
 closeModel(){
  this.showModel = false;
  document.removeEventListener('mouseup', this.closeModel);
 }

 // 组件销毁生命周期
 destroyed(){
  document.removeEventListener('mouseup', this.closeModel);
 }
}
</script>

    接着,重点来了,书写公用封装函数

  我们要在demo组件点击时触发这个函数,即在demo组件里的showMenu事件触发函数,这个函数要利用createElement和appendChild方法将弹出框创建并插入到页面中。

  因为是点击时创建并插入元素,所以为了性能优化,避免有恶意疯狂点击,不断创建和插入元素,我们利用throttle-debounce插件做一个节流。

  先直接看代码,其他注释写在了代码里,函数名随意取:ModelFun

// 文件路径参考: src > components > PublicModel > index.ts
import Vue from 'vue';
import PublicModel from './index.vue'; // 导入上面所写的弹框组件
const throttleDebounce = require('throttle-debounce'); // throttle-debounce插件
const debounce = throttleDebounce.debounce;
const PublicModelConstructor = Vue.extend(PublicModel);
let instance:any;
const initInstance = () => {
 instance = new PublicModelConstructor({
  el: document.createElement('div'),
 });
 document.body.appendChild(instance.$el);
}
const insertInstanceSlot = (slotVNode:any, $event:any) => { // 这里两个参数一个是弹框里插槽的组件,还有就是点击的事件对象(方便定位弹框位置)
 if(!instance){
  initInstance()
 }
 instance.$slots.default = [slotVNode]; // 将传递过来的插槽组件插入弹框组件中
 instance.handleOpen($event) // 触发弹框组件(见上一段代码)的弹框获取定位信息并显示的事件
}
const ModelFun = debounce(200, false, insertInstanceSlot) // 使用throttle-debounce里的debounce保证在一系列调用时间中回调函数只执行一次,这里是200毫秒               // 第二个参数为false时,在点击时会在200毫秒后再执行callback(即insertInstanceSlot),但为true时,会立即先执行一次;
export default ModelFun

    接着,重点来了,书写公用封装函数

  我们要在demo组件点击时触发这个函数,即在demo组件里的showMenu事件触发函数,这个函数要利用createElement和appendChild方法将弹出框创建并插入到页面中。

  因为是点击时创建并插入元素,所以为了性能优化,避免有恶意疯狂点击,不断创建和插入元素,我们利用throttle-debounce插件做一个节流。

  先直接看代码,其他注释写在了代码里,函数名随意取:ModelFun

// 文件路径参考: src > components > PublicModel > index.tsimport Vue from 'vue';
import PublicModel from './index.vue'; // 导入上面所写的弹框组件
const throttleDebounce = require('throttle-debounce'); // throttle-debounce插件
const debounce = throttleDebounce.debounce;
const PublicModelConstructor = Vue.extend(PublicModel);
let instance:any;
const initInstance = () => {
 instance = new PublicModelConstructor({
  el: document.createElement('div'),
 });
 document.body.appendChild(instance.$el);
}
const insertInstanceSlot = (slotVNode:any, $event:any) => { // 这里两个参数一个是弹框里插槽的组件,还有就是点击的事件对象(方便定位弹框位置)
 if(!instance){
  initInstance()
 }
 instance.$slots.default = [slotVNode]; // 将传递过来的插槽组件插入弹框组件中
 instance.handleOpen($event) // 触发弹框组件(见上一段代码)的弹框获取定位信息并显示的事件
}
const ModelFun = debounce(200, false, insertInstanceSlot) // 使用throttle-debounce里的debounce保证在一系列调用时间中回调函数只执行一次,这里是200毫秒               // 第二个参数为false时,在点击时会在200毫秒后再执行callback(即insertInstanceSlot),但为true时,会立即先执行一次;export default ModelFun

    最后,我们回过头来完善一下demo组件

     利用vue的 $createElement 将ActionList组件插入弹框中,并将数据和事件传递给ActionList组件,这里我们传递的事件是简单的弹出我们点击的数据

// 文件路径参考: src > views > demo> index.vue<template>
 <div class="demo-wrapper">
  <div class="demo-div">
   <span>更多功能</span>
   <i class="xk-icon xk-ellipsis" @click.stop='showMenu($event)'></i>
  </div>
 </div>
</template>

<script lang="ts">
 import { Vue, Component, Prop, Watch} from "vue-property-decorator";
 import ActionList from "@/components/ActionList/index.vue";
 import modelFun from "@/components/PublicModel/index";
 @Component({

 })
 export default class articleView extends Vue {
  menuList: string[] = ['菜单1','菜单2','菜单3'];
  menuClick(name:string){ // 弹框里插槽的点击事件
   this.$message({message:name,type:'success'})
  }
  showMenu($event:any){
   modelFun(
    this.$createElement(
     ActionList,
     {
      props: { menu:this.menuList },
      on:{
       click: this.menuClick,
      }
     }
    ),
    $event
   )
  }
 };
</script>

  至此,效果如下

vue实现点击出现操作弹出框的示例

最后,我们利用element ui 的 tree 组件结合我们封装的弹框看一下效果
代码:

<template>
 <div class="demo-wrapper">
  <el-tree
    :data="data"
   node-key="id"
    :default-expand-all="true"
   :expand-on-click-node="false"
   show-checkbox
   >
    <div class="custom-tree-node tree-item" iv slot-scope="{ node }">
     <span>{{ node.label }}</span>
     <span
      class="action"
      @click.stop="showMenu($event)"
     >
      <i class="el-icon-more"></i>
     </span>
    </div>
   </el-tree>
 </div>
</template>

<script lang="ts">
 import { Vue, Component, Prop, Watch} from "vue-property-decorator";
 import ActionList from "@/components/ActionList/index.vue";
 import modelFun from "@/components/PublicModel/index";
 @Component({

 })
 export default class articleView extends Vue {
  menuList: string[] = ['菜单1','菜单2','菜单3'];
  data:any[] = [{
  id: 1,
  label: '一级 1',
  children: [{
   id: 4,
   label: '二级 1-1',
   children: [{
   id: 9,
   label: '三级 1-1-1'
   }, {
   id: 10,
   label: '三级 1-1-2'
   }]
  }]
  }, {
  id: 2,
  label: '一级 2',
  children: [{
   id: 5,
   label: '二级 2-1'
  }, {
   id: 6,
   label: '二级 2-2'
  }]
  }, {
  id: 3,
  label: '一级 3',
  children: [{
   id: 7,
   label: '二级 3-1'
  }, {
   id: 8,
   label: '二级 3-2'
  }]
  }];
  menuClick(name:string){
   console.log(name)
   this.$message({message:name,type:'success'})
  }
  showMenu($event:any){
   modelFun(
    this.$createElement(
     ActionList,
     {
      props: { menu:this.menuList },
      on:{
       click: this.menuClick,
      }
     }
    ),
    $event
   )
  }
 };
</script>

效果:

vue实现点击出现操作弹出框的示例

以上就是vue实现点击出现操作弹出框的示例的详细内容,更多关于vue 弹出框的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
javascript 拖放效果实现代码
Jan 22 Javascript
jQuery EasyUI API 中文文档 - NumberSpinner数值微调器使用介绍
Oct 21 Javascript
jQuery学习笔记 操作jQuery对象 文档处理
Sep 19 Javascript
文本框回车提交与禁止提交示例
Sep 27 Javascript
jquery实现的随机多彩tag标签随机颜色和字号大小效果
Mar 27 Javascript
jQuery之DOM对象和jQuery对象的转换与区别分析
Jan 08 Javascript
jQuery团购倒计时特效实现方法
May 07 Javascript
Javascript 两种刷新方法以及区别和适用范围
Jan 17 Javascript
js实现时间轴自动排列效果
Mar 09 Javascript
JavaScript原生实现观察者模式的示例
Dec 15 Javascript
JS插件clipboard.js实现一键复制粘贴功能
Dec 04 Javascript
解决echarts中横坐标值显示不全(自动隐藏)问题
Jul 20 Javascript
nuxt 自定义 auth 中间件实现令牌的持久化操作
Nov 05 #Javascript
Vant 在vue-cli 4.x中按需加载操作
Nov 05 #Javascript
前端vue如何使用高德地图
Nov 05 #Javascript
解决vue项目中遇到 Cannot find module ‘chalk‘ 报错的问题
Nov 05 #Javascript
vue 全局封装loading加载教程(全局监听)
Nov 05 #Javascript
vant组件中 dialog的确认按钮的回调事件操作
Nov 04 #Javascript
Array.filter中如何正确使用Async
Nov 04 #Javascript
You might like
PHP编译安装中遇到的两个错误和解决方法
2014/08/20 PHP
PHP实现多图上传和单图上传功能
2018/05/17 PHP
PHP二维索引数组的遍历实例分析【2种方式】
2019/06/24 PHP
js异或加解密效果代码
2008/06/25 Javascript
jquery向.ashx文件post中文乱码问题的解决方法
2011/03/28 Javascript
Jquery 绑定时间实现代码
2011/05/03 Javascript
JS实现仿微博可关闭弹出层效果
2015/09/21 Javascript
鼠标悬停小图标显示大图标
2016/01/22 Javascript
完美实现八种js焦点轮播图(下篇)
2020/04/20 Javascript
详解AngularJs中$resource和restfu服务端数据交互
2016/09/21 Javascript
使用jQuery和ajax代替iframe的方法(详解)
2017/04/12 jQuery
jquery网页加载进度条的实现
2017/06/01 jQuery
jquery仿京东商品放大浏览页面
2017/06/06 jQuery
jQuery实现可兼容IE6的遮罩功能详解
2017/09/19 jQuery
《javascript设计模式》学习笔记一:Javascript面向对象程序设计对象成员的定义分析
2020/04/07 Javascript
通过实例解析vuejs如何实现调试代码
2020/07/16 Javascript
浅谈javascript事件环微任务和宏任务队列原理
2020/09/12 Javascript
Antd的table组件表格的序号自增操作
2020/10/27 Javascript
Antd中单个DatePicker限定时间输入范围操作
2020/10/29 Javascript
[46:02]DOTA2上海特级锦标赛D组资格赛#2 Liquid VS VP第二局
2016/02/28 DOTA
Python多进程机制实例详解
2015/07/02 Python
Python的Django框架中URLconf相关的一些技巧整理
2015/07/18 Python
Django之使用celery和NGINX生成静态页面实现性能优化
2019/10/08 Python
在Python中使用MySQL--PyMySQL的基本使用方法
2019/11/19 Python
pytorch的batch normalize使用详解
2020/01/15 Python
python利用paramiko实现交换机巡检的示例
2020/09/22 Python
mui几种页面跳转方式对比总结概括
2017/08/18 HTML / CSS
西班牙创意礼品和小工具网上商店:Curiosite
2016/07/26 全球购物
精选干货:Java精选笔试题附答案
2014/01/18 面试题
测控技术与仪器个人求职信范文
2013/12/30 职场文书
赔偿协议书范本
2014/09/12 职场文书
vue实现同时设置多个倒计时
2021/05/20 Vue.js
Oracle安装TNS_ADMIN环境变量设置参考
2021/11/01 Oracle
Python必备技巧之函数的使用详解
2022/04/04 Python
uniapp 微信小程序 自定义tabBar 导航
2022/04/22 Javascript
Redis基本数据类型哈希Hash常用操作命令
2022/06/01 Redis