vue 2.0封装model组件的方法

本文介绍了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,可滚动

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 利用Vue v-model实现一个自定义的表单组件

    功能描述: 通过点击按钮,可以增减购物数量 组件名称是 CouterBtn 最终效果如下 我们使用 vue-cli搭建基本的开发环境,这也是最快的进行 .vue组件开发的方式 对于入口组件  App.vue (可以暂时忽略其他细节,我们的重点是如何写组件) App.vue <template> <div id="app"> <h4>这是一个利用 v-model实现的自定义的表单组件</h4> <h6>CouterBtn组件的值

  • Vue2.0利用 v-model 实现组件props双向绑定的优美解决方案

    在项目中开始使用vue2来构建项目了,跟 vue1 很大的一处不同在于2 取消了props 的双向绑定,改成只能从父级传到子级的单向数据流,初衷当然是好的,为了避免双向绑定在项目中容易造成的数据混乱. 解决方案一 然后开始参考网上和github上的方案等等,发现很多解决方案是这样的 用data对象中创建一个props属性的副本 watch props属性 赋予data副本 来同步组件外对props的修改 watch data副本,emit一个函数 通知到组件外 这里以最常见的 modal为例子:

  • vue 2.0组件与v-model详解

    前言 大家可能乍一看这个标题,可能会有疑问:v-model和组件也能扯到一起?在打算写这篇文章的时候,也是这么想的.咱们按简历的那一套STAR法则来梳理一下这篇文章: 情景[Situation]: 编写通用的输入组件时,子组件要绑定到父组件的某个变量上dataA,当父组件要拿到自组件的值时不能通过this.$children.xxx取值然后付给dataA, 而是父组件可以直接this.dataA就可以取到当前子组件最新值. 任务[Task]: 实现在父组件直接this.dataA就可以取到当前子

  • vue 2.0封装model组件的方法

    本文介绍了vue 2.0封装model组件的方法,分享给大家,希望对大家有所帮助 单文件组件 使用单文件组件封装model的模板.逻辑和样式,之后就可以在页面中调用此通用组件. 需求 model有两个使用场景: 1.备注/修改密码(简易): 在屏幕中垂直居中 2.添加/修改/展示信息(复杂): 距离屏幕顶部200px,内容过长时可滚动. 3.常规要求(共同点): 标题,关闭icon 点击确定/关闭/遮罩,隐藏model组件 分析上述需求点,得到如下图: wrapper:负责遮盖屏幕 inner:

  • Vue使用v-model封装el-pagination组件的全过程

    使用v-model绑定分页信息对象,分页信息对象包括3个核心属性参数,分页事件直接绑定查询数据的方法,消除父组件的handleSizeChange和handleCurrentChange的绑定事件方法. 1.前言   通过封装el-pagination组件开发自定义分页组件的类似文章网上已经有很多了,但看了一圈,总是不如意,于是决定还是自己动手搞一个. 2.背景 2.1.常规分页处理方法   利用el-pagination组件的常规做法如下:   模板部分: <el-pagination @si

  • Vue的轮播图组件实现方法

    今天在上慕课老师fishenal的vue实战课程的时候,有一个轮播图组件实现,在跟着做的时候,自己也踩了一些坑.此外,在原课程案例的基础上,我加入了不同方向的滑动功能. 本文章采用Vue结合Css3来实现轮播图. 首先要了解的是Vue的动画原理.在vue中,如果我们要给元素设置动画效果,则需要使用一个<transition name="targetClassName"></transition>将相应的元素包裹住,如下: <transition name=

  • Vue开发之封装分页组件与使用示例

    本文实例讲述了Vue开发之封装分页组件与使用.分享给大家供大家参考,具体如下: 使用elementui中的el-pagination来封装分页组件 pagination.vue: <template> <div class="pagination"> <el-pagination small class="text-center" @size-change="handleSizeChange" @current-ch

  • Vue结合Element-Plus封装递归组件实现目录示例

    目录 前言 用正则匹配出所有的h标签并且保存在数组中 封装函数,将数组中的内容变成父子结构 封装递归组件fold-item(在使用之前不要忘了导入自己哦) 在foldMenu中使用递归组件 使用效果 前言 在写我的个人博客网站,用MarkDownIt将md解析成html时,我一直在想,怎么才能实现官方文档他们那些可折叠的目录结构呢?我有那么多标题(h1...h5),而且有的文章是只有h2或者h3的,难道我要在目录组件里面一个个v-if来渲染这些标题达到目录的效果嘛?这个问题在我某一天看vue文档

  • vue 为什么要封装全局组件引入

    目录 1.为什么要封装全局组件引入 2. 封装全局组件的 js 3. 在 main.js 中 4. 我们要引入这些公共组件就可以直接用啦 1.为什么要封装全局组件引入 为何要封装一个封装全局组件引入,因为我们平日定义多个全局组件的时候,在 main.js 里进行单个全局组件的时候太麻烦了,有10个全局组件要 import 10次,还要 Vue.use(组件) 10次,太麻烦了.我们现在手动封装一下. 现在 common 文件夹下面有3 个全局组件,global.js 是我们对全局引入的代码的封装

  • Vue $emit $refs子父组件间方法的调用实例

    1.$emit 子组件调用父组件的方法并传递数据 注意:子组件标签中的时间也不区分大小写要用"-"隔开 子组件: <template> <button @click="emitEvent">点击我</button> </template> <script> export default { data() { return { msg: "我是子组件中的数据" } }, methods:

  • vue cli2.0单页面title修改方法

    一.npm install vue-wechat-title --save  执行命令 二.在main.js中添加 Vue.use(VueWechatTitle); Vue.config.productionTip= false 三.在router/index.js文件中添加 routes: [{ path: '/',redirect: 'Home' },{ path: '/Home',name: 'Home',component: Home, meta:{ title:'银行开户' }},],

  • vue3.0手动封装分页组件的方法

    本文实例为大家分享了vue3.0手动封装分页组件的具体代码,供大家参考,具体内容如下 1.父组件引入 src/views/goods/components/goods-comment.vue <!-- page表示初始化分页时,默认显示第几页 --> <XtxPagination @change-page='changePage' :pagesize='reqParams.pageSize' :total='total' :page='1' /> //调接口 import {fin

  • 详解Vue 2.0封装axios笔记

    前言 单页面应用大多采用前后端分离开发思路,我们知道,前端和后端交互有多中方式(服务器端渲染.Ajax.websocket等),今天我们主要讲解Ajax部分. 最近团队讨论了一下,Ajax 本身跟 Vue 并没有什么需要特别整合的地方,使用 fetch polyfill 或是 axios.superagent 等等都可以起到同等的效果,vue-resource 提供的价值和其维护成本相比并不划算,所以决定在不久以后取消对 vue-resource 的官方推荐.已有的用户可以继续使用,但以后不再把

随机推荐