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 html 静态页面传参数
Apr 10 Javascript
JavaScript Eval 函数使用
Mar 23 Javascript
js判断输入是否为正整数、浮点数等数字的函数代码
Nov 17 Javascript
这些年、我收集的JQuery代码小结
Aug 01 Javascript
JQuery入门——事件切换之hover()方法应用介绍
Feb 05 Javascript
如何使Chrome控制台支持多行js模式——意外发现
Jun 13 Javascript
javascript实现的一个带下拉框功能的文本框
May 08 Javascript
JS模拟的Map类实现方法
Jun 17 Javascript
vue中引入第三方字体文件的方法示例
Dec 17 Javascript
微信小程序实现人脸识别登陆的示例代码
Apr 02 Javascript
常见的浏览器存储方式(cookie、localStorage、sessionStorage)
May 07 Javascript
小程序如何使用分包加载的实现方法
May 22 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
Zend Guard一些常见问题解答
2008/09/11 PHP
php中使用__autoload()自动加载未定义类的实现代码
2013/02/06 PHP
深入php中var_dump方法的使用详解
2013/06/24 PHP
PHP常用工具类大全附全部代码下载
2015/12/07 PHP
Yii框架连接mongodb数据库的代码
2016/07/27 PHP
javascript 简单高效判断数据类型 系列函数 By shawl.qiu
2007/03/06 Javascript
JQuery下关于$.Ready()的分析
2009/12/13 Javascript
jquery easyui的tabs使用时的问题
2010/03/23 Javascript
如何将JS的变量值传递给ASP变量
2012/12/10 Javascript
原生javascript兼容性测试实例
2013/07/01 Javascript
javascript封装简单实现方法
2015/08/11 Javascript
vue.js实现仿原生ios时间选择组件实例代码
2016/12/21 Javascript
Bootstrap笔记—折叠实例代码
2017/03/13 Javascript
AngularJS基于provider实现全局变量的读取和赋值方法
2017/06/28 Javascript
详解Vue中一种简易路由传参办法
2017/09/15 Javascript
使用原生js+canvas实现模拟心电图的实例
2017/09/20 Javascript
浅谈JavaScript 代码简洁之道
2019/01/09 Javascript
详解jQuery-each()方法
2019/03/13 jQuery
详解如何模拟实现node中的Events模块(通俗易懂版)
2019/04/15 Javascript
详解在vue-cli3.0中自定css、js和图片的打包路径
2019/08/26 Javascript
js中console在一行内打印字符串和对象的方法
2019/09/10 Javascript
[03:04]2018年度DOTA2玩家最喜爱的主播-完美盛典
2018/12/16 DOTA
python模块restful使用方法实例
2013/12/10 Python
Python使用xlrd读取Excel格式文件的方法
2015/03/10 Python
python脚本生成caffe train_list.txt的方法
2018/04/27 Python
基于Python List的赋值方法
2018/06/23 Python
python 爬虫 实现增量去重和定时爬取实例
2020/02/28 Python
ECCO爱步加拿大官网:北欧丹麦鞋履及皮具品牌
2017/07/08 全球购物
简单的JAVA编程面试题
2013/03/19 面试题
幼儿教师培训感言
2014/03/08 职场文书
2015年秋季小班开学寄语
2015/05/27 职场文书
2016入党心得体会范文
2016/01/06 职场文书
《社戏》教学反思
2016/02/22 职场文书
Java常用工具类汇总 附示例代码
2021/06/26 Java/Android
Java 语言中Object 类和System 类详解
2021/07/07 Java/Android
NASA 机智号火星直升机拍到了毅力号设备碎片
2022/04/29 数码科技