您的当前位置:首页正文

vue 2.0封装model组件的方法

2020-11-27 来源:易榕旅网

本文介绍了vue 2.0封装model组件的方法,分享给大家,希望对大家有所帮助

单文件组件

使用单文件组件封装model的模板、逻辑和样式,之后就可以在页面中调用此通用组件。

需求

model有两个使用场景:

1、备注/修改密码(简易):

在屏幕中垂直居中
2、添加/修改/展示信息(复杂):

距离屏幕顶部200px,内容过长时可滚动。

3、常规要求(共同点):

标题,关闭icon

点击确定/关闭/遮罩,隐藏model组件

分析上述需求点,得到如下图:


  • wrapper:负责遮盖屏幕
  • inner:负责垂直居中/距顶部200px
  • title:可变化标题
  • content:可变化的内容区域
  • 方案

    1、Prop传参
    title(标题)、show(隐藏/显示)、width(宽度)、type(居中/顶部)

    2、自定义事件
    关闭model

    3、slot分发
    内容区域可自定义

    4、滚动穿透

    具体实现

    template

     <div class="model-mask" v-show="show">
     <div :class="[type === 'top' ? 'model-wrapper-top' : 'model-wrapper']" @click="close">
     <div :class="[type === 'top' ? 'model-container-top' : 'model-container']"
     :style="{width:width + 'px'}">
     <div class="model-header">
     <span>{{title}}</span>
     <i class="close-empty" @click="close">
     <Icon
     type="ivu-icon ivu-icon-ios-close-empty"
     size="25" />
     </i>
     </div>
     <div class="model-body">
     <slot></slot>
     </div>
     </div>
     </div>
     </div>
    

    script

     export default {
     name: 'MyModel',
     props:
     {
     title: String,
     show: Boolean,
     width: Number,
     type: String
     },
     data () {
     return {
     scrollTop: ''
     }
     },
     watch: {
     show: function (val, oldVal) {
     function getScrollTop () {
     return document.body.scrollTop || document.documentElement.scrollTop
     }
     if (val) {
     // 在弹出层显示之前,记录当前的滚动位置
     this.scrollTop = getScrollTop()
     let body = document.querySelector('body')
     body.className = 'not-scroll'
     // 把脱离文档流的body拉上去!否则页面会回到顶部!
     document.body.style.top = -this.scrollTop + 'px'
     }
     }
     },
     methods: {
     close: function (e) {
     function to (scrollTop) {
     document.body.scrollTop = document.documentElement.scrollTop = scrollTop
     }
     let target = e.srcElement || e.target
     if (target.className === 'model-wrapper' ||
     target.className.indexOf('ivu-icon-ios-close-empty') > -1 ||
     target.className === 'model-wrapper-top') {
     this.$emit('close')
     let body = document.querySelector('body')
     body.className = ''
     // 滚回到老地方!
     to(this.scrollTop)
     }
     }
     }
    }
    

    style

     <style scoped lang="scss">
    .model-mask {
     height: 100%;
     position: fixed;
     top: 0;
     bottom: 0;
     left: 0;
     right: 0;
     z-index: 1000;
     background: rgba(0, 0, 0, .5);
    }
    /**
     * 垂直居中
     */
    .model-wrapper {
     height: 100%;
     text-align: center;
    }
    .model-wrapper:before {
     content: "";
     display: inline-block;
     height: 100%;
     vertical-align: middle;
    }
    .model-container {
     position: relative;
     display: inline-block;
     vertical-align: middle;
     background-color: white;
     text-align: left;
     box-shadow: 0 5px 14px 0 rgba(0,0,0,0.15);
     border-radius: 6px;
     overflow: hidden;
     z-index: 1050;
    }
    /**
     * 距离顶部100px,可滚动
     */
    .model-wrapper-top {
     position: relative;
     height: 100%;
     overflow-x: hidden;
     overflow-y: scroll;
    }
    .model-container-top {
     margin: 100px auto;
     background-color: white;
     text-align: left;
     box-shadow: 0 5px 14px 0 rgba(0,0,0,0.15);
     border-radius: 6px;
     overflow: hidden;
    }
    .close-empty {
     position: absolute;
     right: 16px;
     top: 10px;
     overflow: hidden;
     cursor: pointer;
     z-index: 1100;
    }
    .model-header {
     position: relative;
     height: 45px;
     line-height: 45px;
     padding: 0 20px;
     font-size: 14px;
     color: #999;
     border-bottom: 1px solid #eee;
    }
    </style>
    

    引用

     <button type="button" @click="showModel">戳我呀</button>
    import MyModel from '../componets/model.vue'
    export default {
     name: 'test',
     components: {
     MyModel
     },
     data () {
     return {
     show: false
     }
     },
     methods: {
     /**
     * 打开model
     */
     closeModel: function () {
     this.show = false
     },
     /**
     * 关闭model
     */
     showModel: function () {
     this.show = true
     }
     }
    }
    

    引用一

     <my-model title="标题" :width="400" :show="show" v-on:close="closeModel">
     <!-- slot -->
     <div class="tips">
     <p>this is content area。</p>
     </div>
     </my-model>
    

    引用二

     <my-model type="top" title="标题" :width="400" :show="show" v-on:close="closeModel">
     <!-- slot -->
     <div class="tips">
     <p v-for="i in 50">this is content area。</p>
     </div>
     </my-model>
    

    demo

    垂直居中


    距顶部200px,可滚动

    显示全文