论如何用Vue实现一个弹窗-一个简单的组件实现

简介: 最近在使用element-ui框架,用到了Dialog对话框组件,大致实现的效果,跟我之前自己在移动端项目里面弄的一个弹窗组件差不太多。然后就想着把这种弹窗组件的实现方式与大家分享一下,下面本文会带着大家手摸手实现一个弹窗组件。本文主要内容会涉及到弹窗遮罩的实现,slot插槽的使用方式,props、$emit传参,具体组件代码也传上去了。如果喜欢的话可以点波赞/关注,支持一下,希望大家看完本文可以有所收获。

image.png

前言

最近在使用element-ui框架,用到了Dialog对话框组件,大致实现的效果,跟我之前自己在移动端项目里面弄的一个弹窗组件差不太多。然后就想着把这种弹窗组件的实现方式与大家分享一下,下面本文会带着大家手摸手实现一个弹窗组件。

本文主要内容会涉及到弹窗遮罩的实现,slot插槽的使用方式,props$emit传参,具体组件代码也传上去了。如果喜欢的话可以点波赞/关注,支持一下,希望大家看完本文可以有所收获。


组件最后实现的效果

image.png

实现步骤

  1. 先搭建组件的html和css样式,遮罩层和内容层。
  2. 定制弹窗内容:弹窗组件通过slot插槽接受从父组件那里传过来弹窗内容。
  3. 定制弹窗样式:弹窗组件通过props接收从父组件传过来的弹窗宽度,上下左右的位置。
  4. 组件开关:通过父组件传进来的props控制组件的显示与隐藏,子组件关闭时通过事件$emit触发父组件改变值。

1.搭建组件的html和css样式。

html结构:一层遮罩层,一层内容层,内容层里面又有一个头部title和主体内容和一个关闭按钮。

下面是组件中的html结构,里面有一些后面才要加进去的东西,如果看不懂的话可以先跳过,

<template>
  <div class="dialog">
      <!--外层的遮罩 点击事件用来关闭弹窗,isShow控制弹窗显示 隐藏的props-->
      <div class="dialog-cover back"  v-if="isShow"  @click="closeMyself"></div>
      <!-- transition 这里可以加一些简单的动画效果 -->
      <transition name="drop">
         <!--style 通过props 控制内容的样式  -->
        <div class="dialog-content" :style="{top:topDistance+'%',width:widNum+'%',left:leftSite+'%'}"  v-if="isShow">
          <div class="dialog_head back">
             <!--弹窗头部 title-->
              <slot name="header">提示信息</slot>
          </div>
          <div class="dialog_main" :style="{paddingTop:pdt+'px',paddingBottom:pdb+'px'}">
            <!--弹窗的内容-->
            <slot name="main">弹窗内容</slot>
          </div>
          <!--弹窗关闭按钮-->
          <div  class="foot_close" @click="closeMyself">
              <div class="close_img back"></div>
          </div>
        </div>
    </transition>
  </div>
</template>

下面是组件中的主要的css样式,里面都做了充分的注释,主要通过z-indexbackground达到遮罩的效果,具体内容的css可以根据自己的需求来设置。

<style lang="scss" scoped>
 // 最外层 设置position定位 
  .dialog {
    position: relative;
    color: #2e2c2d;
    font-size: 16px;
  }
  // 遮罩 设置背景层,z-index值要足够大确保能覆盖,高度 宽度设置满 做到全屏遮罩
  .dialog-cover {
    background: rgba(0,0,0, 0.8);
    position: fixed;
    z-index: 200;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
  // 内容层 z-index要比遮罩大,否则会被遮盖,
  .dialog-content{
    position: fixed;
    top: 35%;
    // 移动端使用felx布局 
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    z-index: 300;
 }
</style>

2. 通过slot定制弹窗内容

这一步,只要理解了slot的作用以及用法,就没有问题了。

单个插槽:

<slot>这是在没有slot传进来的时候,才显示的弹窗内容</slot>

上面是单个插槽也叫默认插槽,在父组件中使用插槽的正确姿势:

<my-component>
   <!--在my-component里面的所有内容片段都将插入到slot所在的DOM位置,并且会替换掉slot标签-->
   <!--这两个p标签,将替换整个slot标签里面的内容-->
    <p>这是一些初始内容</p>
    <p>这是更多的初始内容</p>
  </my-component>

ps:如果子组件里面包含slot插槽,那么上面的p标签的内容将会被丢弃。

具名插槽:

所谓的具名插槽,即为slot标签赋一个name属性,具名插槽可以父组件中不同的内容片段放到子组件的不同地方,具名插槽还是可以拥有一个默认插槽。下面可以看一下弹窗组件插槽的使用方式:

<div class="dialog_head back ">
  <!--弹窗头部 title-->
  <slot name="header">提示信息</slot>
 </div>
 <div class="dialog_main " :style="{paddingTop:pdt+'px',paddingBottom:pdb+'px'}">
    <!--弹窗的内容-->
    <slot name="main">弹窗内容</slot>
 </div>

在父组件中的使用方式:

  1. 将弹窗组件引入要使用的组件中,并通过components注册成为组件。
  2. 父组件中弹窗组件插槽的使用方法如下。
<dialogComponent>
     <div slot="header">插入到name为header的slot标签里面</div>
      <div class="dialog_publish_main" slot="main">
         这里是内容插入到子组件的slot的name为main里面,可以在父组件中添加class定义样式,事件类型等各种操作
      </div>
 </dialogComponent>

关于组件中用到的插槽的介绍就到这里了,插槽在弹窗组件中的应用是一个典型的栗子,可以看到插槽作用相当强大,而插槽本身的使用并不难,同学们爱上插槽了没有?


3.通过props控制弹窗显隐&&定制弹窗style

psops是Vue中父组件向子组件传递数据的一种方式,不熟悉的小伙伴们可以看一下props文档

因为弹窗组件都是引到别的组件里面去用的,为了适合不同组件场景中的弹窗,所以弹窗组件必须具备一定的可定制性,否则这样的组件将毫无意义,下面介绍一下props的使用方式,以弹窗组件为例:

  1. 首先需要在被传入的组件中定义props的一些特性,验证之类的。
  2. 然后在父组件中绑定props数据。
<script>
export default {
  props: {
    isShow: { 
    //弹窗组件是否显示 默认不显示
      type: Boolean,
      default: false,
      required:true, //必须
    },
    //下面这些属性会绑定到div上面 详情参照上面的html结构
    // 如: :style="{top:topDistance+'%',width:widNum+'%'}"
    widNum:{ 
    //内容宽度
      type: Number,
      default:86.5
    },
    leftSite:{
      // 左定位
      type: Number,
      default:6.5
    },
    topDistance: {
        //top上边距
      type: Number,
      default:35
    },
    pdt:{
      //上padding
      type: Number,
      default:22
    },
    pdb:{
      //下padding
      type: Number,
      default:47
    }
  },
}
</script>

父组件中使用方式:

<dialogComponent :is-show="status.isShowPublish" :top-distance="status.topNum">
 </dialogComponent>

ps:props传递数据不是双向绑定的,而是单向数据流,父组件的数据变化时,也会传递到子组件中,这就意外着我们不应该在子组件中修改props。所以我们在关闭弹窗的时候就需要通过$emit来修改父组件的数据,然后数据会自动传到子组件中。

现在基本上弹窗组件都已实现的差不多了,还差一个弹窗的关闭事件,这里就涉及到子组件往父组件传参了。

4.$emit触发父组件事件修改数据,关闭弹窗

Vue中在子组件往父组件传参,很多都是通过$emit来触发父组件的事件来修改数据。

在子组件中,在点击关闭,或者遮罩层的时候触发下面这个方法:

methods: {
    closeMyself() {
      this.$emit("on-close"); 
      //如果需要传参的话,可以在"on-close"后面再加参数,然后在父组件的函数里接收就可以了。
    }
  }

父组件中的写法:

<dialogComponent :is-show="status.isShowPublish" :top-distance="status.topNum"  @on-close="closeDialog"> 
  </dialogComponent>
  //"on-close是监听子组件的时间有没有触发,触发的时候执行closeDialog函数
methods:{
  closeDialog(){
    // this.status.isShowPublish=false;
    //把绑定的弹窗数组 设为false即可关闭弹窗
  },
}

可以用弹窗组件实现下列这种信息展示,或者事件交互:

image.png

弹窗组件代码

上面是把弹窗的每个步骤拆分开来,一步步解析的,每一步都说的比较清楚了,具体连起来的话,可以看看代码,再结合文章就能理的很清楚了。

小结:

这个弹窗组件,实现起来一点都不难,我这里主要是提供了一个实现方式,当项目中有需要的话,大家也可以自己撸一个出来,以上就是本文的内容了,希望同学们看完能有所收获。

目录
相关文章
|
17天前
|
JavaScript API 开发者
Vue是如何进行组件化的
Vue是如何进行组件化的
|
14天前
|
缓存 JavaScript UED
Vue3中v-model在处理自定义组件双向数据绑定时有哪些注意事项?
在使用`v-model`处理自定义组件双向数据绑定时,要仔细考虑各种因素,确保数据的准确传递和更新,同时提供良好的用户体验和代码可维护性。通过合理的设计和注意事项的遵循,能够更好地发挥`v-model`的优势,实现高效的双向数据绑定效果。
117 64
|
14天前
|
前端开发 JavaScript 测试技术
Vue3中v-model在处理自定义组件双向数据绑定时,如何避免循环引用?
Web 组件化是一种有效的开发方法,可以提高项目的质量、效率和可维护性。在实际项目中,要结合项目的具体情况,合理应用 Web 组件化的理念和技术,实现项目的成功实施和交付。通过不断地探索和实践,将 Web 组件化的优势充分发挥出来,为前端开发领域的发展做出贡献。
24 8
|
14天前
|
JavaScript
在 Vue 3 中,如何使用 v-model 来处理自定义组件的双向数据绑定?
需要注意的是,在实际开发中,根据具体的业务需求和组件设计,可能需要对上述步骤进行适当的调整和优化,以确保双向数据绑定的正确性和稳定性。同时,深入理解 Vue 3 的响应式机制和组件通信原理,将有助于更好地运用 `v-model` 实现自定义组件的双向数据绑定。
|
17天前
|
JavaScript 前端开发 开发者
Vue是如何进行组件化的
Vue是如何进行组件化的
|
17天前
|
存储 JavaScript 前端开发
介绍一下Vue的核心功能
介绍一下Vue的核心功能
|
19天前
|
JavaScript 前端开发 开发者
vue 数据驱动视图
总之,Vue 数据驱动视图是一种先进的理念和技术,它为前端开发带来了巨大的便利和优势。通过理解和应用这一特性,开发者能够构建出更加动态、高效、用户体验良好的前端应用。在不断发展的前端领域中,数据驱动视图将继续发挥重要作用,推动着应用界面的不断创新和进化。
|
20天前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱前端的大一学生,专注于JavaScript与Vue,正向全栈进发。博客分享Vue学习心得、命令式与声明式编程对比、列表展示及计数器案例等。关注我,持续更新中!🎉🎉🎉
23 1
vue学习第一章
|
20天前
|
JavaScript 前端开发 索引
vue学习第三章
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中的v-bind指令,包括基本使用、动态绑定class及style等,希望能为你的前端学习之路提供帮助。持续关注,更多精彩内容即将呈现!🎉🎉🎉
22 1
vue学习第三章
|
20天前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
35 1
vue学习第四章