Vue组件化开发之通用型弹出框的实现

本文主要分享关于组件化开发的理解,让刚入门的小伙伴少走一些弯路,提高开发效率,作者本人也是新手,如有不当之处,请大佬指出,感谢。

相信很多刚入门的小伙伴,经常会写很多重复的代码,而这些代码一般情况下也都是大同小异,在这种情况下,如何让开发和学习变得更加高效,组件化的思想就显得尤为重要。这里通过设计一个简单的弹出框,给小伙伴们分享组件化的应用。

组件&组件化

组件化是对某些可以进行复用的功能进行封装的标准化工作。组件一般会内含自身的内部UI元素、样式和JS逻辑代码,它可以很方便的在应用的任何地方进行快速的嵌入。组件内部可以使用其他组件来构成更复杂的组件。

在实际的开发中,我们应该避免去编写重复的代码,将精力放在更加核心的部分,因此就需要将这些重复的代码抽取出来,封装成公共的组件,提高开发效率,但同时也要注意组件的健壮性和可复用性,让它能够尽可能适应更多的场景。

基本结构

首先是弹出框的基本结构

<div class="modal">
   <div class="mask"></div>
   <div class="modal-dialog">
    <div class="modal-header">
     <span>标题</span>
     <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="icon-close"></a>
    </div>
    <div class="modal-body">
     <slot name="body"></slot>
    </div>
    <div class="modal-footer">
      <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="btn">确定</a>
      <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="btn btn-default">取消</a>
     </div>
    </div>
   </div>
  </div>

​ 基本结构很简单,稍微注意一点的就是 slot 插槽,如果没有提供name属性,它将有一个隐含的名字default,并且在父组件如果没有指定 slot 的 v-slot 属性的话,内容会传给default插槽。

在这里定义了 slot 的name属性 body ,这种的叫做具名插槽,会匹配 v-slot:body 的内容。

注意,在父组件中调用需要用 <template> 包裹,并且 <template> 元素中的所有内容都将被传入相应的插槽。

给弹出框加点样式

.modal {
 position: fixed;
 top: 0;
 left: 0;
 width: 100%;
 height: 100%;
 .mask {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #000000;
  opacity: 0.5;
 }
 .modal-dialog {
  position: absolute;
  top: 40%;
  left: 50%;
  width: 560px;
  height: auto;
  background-color: #ffffff;
  transform: translate(-50%, -50%);
  .modal-header {
   height: 60px;
   background-color: #F5F5F5;
   padding: 0 25px;
   line-height: 60px;
   font-size: 16px;
   .icon-close {
    position: absolute;
    top: 23px;
    right: 25px;
    width: 14px;
    height: 14px;
    background: url("/static/img/icon-close.png") no-repeat center;
    background-size: contain;
   }
  }
  .modal-body {
   padding: 42px 40px 54px;
   font-size: 14px;
  }
  .modal-footer {
   height: 82px;
   line-height: 82px;
   text-align: center;
   background-color: #F5F5F5;
  }
 }
}

我这里使用的是 scss ,使用的时候别忘了安装 node-sass 和 sass-loader ,现在我们的页面是这个样子了

虽然还是不太美观,但是已经基本上是一个弹出框的雏形了,并且我没有给 a 标记样式,原因在后面。

SCSS函数

回过头再看看上面的 css 代码,这里重复写了4次固定定位的代码,而且随着项目的推进,肯定还有更多类似的代码,何不将这些部分抽取出来,进行封装呢? scss 提供了这个功能,将 css 封装成函数,这里的函数直接会返回函数体。我们在遇到类似的情况时,就能够直接复用。

在 assets 目录下新建 scss 文件夹并在里面新建 mixin.scss ,在里面新建 position 函数,代码如下:

@mixin position($pos: absolute, $top: 0, $left: 0, $w: 100%, $h: 100%) {
 position: $pos;
 top: $top;
 left: $left;
 width: $w;
 height: $h;
}

接着我们引入 mixin.scss ,用 position 函数替换我们原先的代码

通过@include方式使用 scss 函数: @include position(fixed); 括号里面的是参数。

关于按钮

每一个网站都有很多按钮,不过,同一个网站的按钮风格大多都是一样,无非是大小不一。因此可以单独在 scss 文件下新建 button.scss 然后在 App.vue 里面引入这个文件,在后面除了一些特别的样式,其它就不需要给按钮定义样式了,这样也便于维护。这里给出我的 button 文件,可以参考一下。

.btn {
 display: inline-block;
 width: 110px;
 line-height: 30px;
 text-align: center;
 background-color: #FF6600;
 color: #ffffff;
 border: none;
 cursor: pointer;
}
.btn-default {
 background-color: #b0b0b0;
 color: #d7d7d7;
}
.btn-large {
 width: 202px;
 height: 50px;
 line-height: 50px;
 font-size: 18px;
}
.btn-huge {
 width: 300px;
 height: 54px;
 line-height: 54px;
 font-size: 16px;
}
.btn-group {
 .btn {
  margin-right: 20px;
  &:last-child {
   margin-right: 0;
  }
 }
}

为了复用

当前这个弹出框还只是一个固定的结构,它并不能在其他地方复用,需要进行一些处理,将所有可变部分抽取出来,例如标题,按钮,内容。因为有插槽,所以内容就不用考虑,需要关注的是标题和按钮,因为标题有可能是提示,警告等等,按钮也有可能是确定、取消的一个或两个都有。而这些信息都是从父组件传递过来,需要用 props 接收。

在 props 里面添加如下代码,并给某些属性指定默认值:

props: {
  // 弹框标题
  title: String,
  // 按钮类型: 1:确定按钮 2:取消按钮 3:确定取消
  btnType: String,
  // 按钮文本
  sureText: {
   type: String,
   default: "确定"
  },
  cancleText: {
   type: String,
   default: "取消"
  },
  showModal: Boolean
 }

添加完之后,还需重新改写代码

<div class="modal" v-show="showModal">
   <div class="mask"></div>
   <div class="modal-dialog">
    <div class="modal-header">
     <span>{{title}}</span>
     <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="icon-close" @click="$emit('cancle')"></a>
    </div>
    <div class="modal-body">
     <slot name="body"></slot>
    </div>
    <div class="modal-footer">
      <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="btn" v-if="btnType==1"@click="$emit('submit')"{{sureText}}</a>
      <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="btn" v-if="btnType==2"@click="$emit('cancle')">{{cancleText}}</a>
     <div class="btn-group" v-if="btnType==3">
      <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="btn" @click="$emit('submit')">{{sureText}}</a>
      <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="btn btn-default" @click="$emit('submit')">{{cancleText}}</a>
     </div>
    </div>
   </div>
  </div>

通过父组件传递的参数,来实现代码的重用,并且使用 $emit 来向外抛出自定义事件,然后在父组件实现自己的业务逻辑。

在 Home.vue 里面引入这个组件并调用

<modal
  title="小星星"
  sureText="确定"
  btnType="1"
  :showModal="showModal"
  @submit="go"
  @cancle="showModal=false"
 >
  <template v-slot:body>
   <p>给个小星星吧</p>
  </template>
 </modal>

这里的 @submit 和 @cancle 就是我们在组件里面自定义的事件

最终效果如下

实现完之后,感觉有点弹出时生硬,没关系,我们给它加点动画,在css3中有 transform 和 transition 可以实现动画效果,但是我们这里使用 vue 内置组件 <transition> ,让弹出框有一个从上面弹出的效果。

transition组件

transition 组件可以为元素或组件添加过渡效果,只会把过渡效果应用到其包裹的内容上,而不会额外渲染 DOM 元素,也不会出现在可被检查的组件层级中。它可以通过多种方式进行过渡,在这里应用 class的方式过渡。

这幅图是 Vue 官方给出的图,简单来说,v-enter是动画开始的状态,v-enter-active进入过渡生效时的状态,v-enter-to是过渡的结束状态,leave同理,具体细节大家可以去 https://cn.vuejs.org/v2/guide/transitions.html查看。

当没有指定的name属性时,过渡的类名会默认以v作为前缀,这里给transition指定name为

slide并用它包裹modal组件

<transition name="slide">
  <div class="modal" v-show="showModal">
   ...
   ...
  </div>
 </transition>

在style代码里面modal后面加上

&.slide-enter-active {
  top: 0;
 }
 &.slide-leave-active {
  top: -100%;
 }
 &.slide-enter {
  top: -100%;
 }

并且给modal指定需要过渡的属性

transition: top 0.5s;

加完这个之后,弹出框就会有一个滑上滑下的动画啦。

到此,我们的弹出框就完成啦。

你也可以根据自己的需求去做适当的调整,开发出适合自己项目的弹出框。

最后

在实际开发中,组件化是尤为重要的,它能够帮助我们写出更高质量的代码,也能够让我们的代码更易于维护,尽早的树立组件化的思想,对写代码也是非常有帮助的。

附上https://github.com/anpeier/shop-online

到此这篇关于Vue组件化开发之通用型弹出框的实现的文章就介绍到这了,更多相关Vue 弹出框内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2020-02-28

vue组件实现弹出框点击显示隐藏效果

本文实例为大家分享了vue实现弹出框点击显示隐藏的具体代码,供大家参考,具体内容如下 效果如下图 由于我的更改密码弹出框是一个组件引用的,所以在一开始是隐藏的,这就需要在当前的页面上对弹出框组件设置v-show,但是在弹出框显示出来的时候,操作执行完后当前页面的更改按钮已经被弹出框覆盖了.所以只能在弹出页面点击取消实现关闭隐藏弹出框.这样就需要写两个点击事件,但是两个点击事件就会有冲突,需要点击两下才能使弹出框显示和隐藏.然后我就用的以下方法,希望可以帮到大家!!! 代码如下 1.在当前页面中(

详解用vue编写弹出框组件

前言 最近研究了用vue编写弹出框的组件,发现其实这里面的门道还是有很多的.这篇文完全是用来记录总结下最近的学习成果,同时也希望能够帮得上正在学习纠结的你~ps:本文假设你已经了解vue2.0相关框架,因此适合有一定vue2.0基础的同学阅读. 设计组件的思考 其实单纯的编写一个弹出框组件并不难,写一个模板,然后用v-if或者v-show指令还控制组件的出现与消失.真正困扰我的是,这个组件的调用方式,这个问题纠结了我好久. 调研了下资料,有些人建议,直接把组件标签插进模板中,然后通过直接控制组件

vue弹出框组件封装实例代码

新学vue,参考别人封装弹出层组件.好用! 1.你需要先建一个弹出框的模板: //首先创建一个mack.vue <template> <div class="mack" v-if="isShow"> <div class="mackWeb" :style="text.mackStyle"> <div class="title font_b" v-if="t

使用vue实现各类弹出框组件

简单介绍一下vue中常用dialog组件的封装: 实现动态传入内容,实现取消,确认等回调函数. 首先写一个基本的弹窗样式,如上图所示. 在需要用到弹窗的地方中引入组件: import dialogBar from './dialog.vue' components:{ 'dialog-bar': dialogBar, }, <dialog-bar></dialog-bar> 点击一个按钮显示弹窗,并保证关闭弹窗后再次点击依旧显示 在弹窗组件中定义一个value值:v-model=&

elementUI vue this.$confirm 和el-dialog 弹出框 移动 示例demo

调试了好久, 还能凑合用, 请直接看DOME 示例,复制就能用: <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- import CSS --> <link rel="stylesheet" href="https://u

Android仿QQ长按删除弹出框功能示例

废话不说,先看一下效果图,如果大家感觉不错,请参考实现代码: 对于列表来说,如果想操作某个列表项,一般会采用长按弹出菜单的形式,默认的上下文菜单比较难看,而QQ的上下文菜单就人性化多了,整个菜单给用户一种气泡弹出的感觉,而且会显示在手指按下的位置,而技术实现我之前是使用popupWindow和RecyclerView实现的,上面一个RecyclerView,下面一个小箭头ImageView,但后来发现没有必要,而且可定制化也不高,还是使用多个TextView更好一点. 我封装了一下,只需要一个P

Yii框架弹出框功能示例

本文实例讲述了Yii框架弹出框功能.分享给大家供大家参考,具体如下: <?php $this->beginWidget('zii.widgets.jui.CJuiDialog', array( 'id'=>'userinfo_edit',//弹窗ID // additional javascript options for the dialog plugin 'options'=>array(//传递给JUI插件的参数 'title'=>'修改个人信息', 'autoOpen

layer.confirm点击第一个按钮关闭弹出框的方法

layer.confirm弹出框,当你点击第一个按钮的时候,这个弹出层不会关闭,也是给一些小伙伴带来了一些困扰, 下面分享两个解决方案: ①可以将第一个按钮的回调函数传一个index,然后使用layer.close("index")就可以点击第一个按钮的时候关闭弹出框了,代码如下: ②第二种方法就非常的粗暴了,你可以直接在这个回调函数中写: layer.closeAll('dialog'); 也能实现点击第一个按钮的时候关闭弹出框 以上这篇layer.confirm点击第一个按钮关闭弹

JS模拟Dialog弹出浮动框效果代码

本文实例讲述了JS模拟Dialog弹出浮动框效果代码.分享给大家供大家参考.具体如下: 这里演示JS模拟Dialog弹出浮动框,蓝色经典风格,可以创建一个新层,可设置弹出层的标题和内容,用它可实现一个登录框,或用在后台管理中. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-mn-dialog-float-dlg-style-demo/ 具体代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML

Android解决dialog弹出时无法捕捉Activity的back事件的方法

本文实例讲述了Android解决dialog弹出时无法捕捉Activity的back事件的方法.分享给大家供大家参考.具体分析如下: 在一些情况下,我们需要捕捉back键事件,然后在捕捉到的事件里写入我们需要进行的处理,通常可以采用下面三种办法捕捉到back事件: 1)重写onKeyDown或者onKeyUp方法 2)重写onBackPressed方法 3)重写dispatchKeyEvent方法 这三种办法有什么区别在这里不进行阐述,有兴趣的朋友可以查阅相关资料. 然而在有dialog弹出时,

jquery弹出框插件jquery.ui.dialog用法分析

本文实例讲述了jquery弹出框插件jquery.ui.dialog用法.分享给大家供大家参考,具体如下: 1. jquery.ui.dialog 官方地址 http://jqueryui.net/dialog/ jquery.ui.dialog是一个非常灵活的模式框,它的官方地址为: http://docs.jquery.com/UI/Dialog 2. 文件引用 要使用jquery.ui.dialog,需要引用两个文件,1个是js,另外1个是css 在contentpage中添加: <scr