vue创建一个body作为父元素的弹窗
发布: 2018-07-16 23:42:31标签: vue
分别借鉴elementui的dialog和mint-ui的toast组件
最新版弹窗
01<template>02 <div v-if='visible' class='my-model center-flex'>03 <div @click='close' ref='model' class='bg'></div>04 <div class='wrapper'>05 <slot></slot>06 </div>07 </div>08</template>0910<script>11 export default {12 props: {13 visible: {14 type: Boolean,15 default: true16 },17 appendToBody: {18 type: Boolean,19 default: true20 }21 },22 data() {23 return {24 }25 },26 watch: {27 visible() {28 this.disabledScroll()29 }30 },31 methods: {32 close() {33 this.$emit('close')34 },35 initModel() {36 if (this.appendToBody) {37 document.body.appendChild(this.$el)38 }39 },40 disabledScroll() {41 if (this.visible) {42 this.$nextTick(() => {43 this.$refs.model.ontouchmove = (e) => {44 e.preventDefault()45 }46 })47 }48 }49 },50 mounted() {51 this.initModel()52 this.disabledScroll()53 },54 beforeDestroy() {55 if (this.appendToBody && this.$el && this.$el.parentNode) {56 this.$el.parentNode.removeChild(this.$el);57 }58 }59 }60</script>6162<style lang='scss' scoped>63 .my-model {64 position: fixed;65 left: 0;66 top: 0;67 width: 100%;68 height: 100%;69 }7071 .bg {72 display: block;73 width: 100%;74 height: 100%;75 background: rgba(0, 0, 0, 0.3);76 position: absolute;77 left: 0;78 top: 0;79 }8081 .wrapper {82 position: relative;83 z-index: 1;84 background: white;85 }86</style>87
复制代码老版本弹窗
model.js
01import Vue from 'vue'0203const Model = Vue.extend(require('./MyModel').default)04let instance0506export default {07 show(component) {08 if (!instance) {09 // 第一次创建10 instance = new Model({11 el: document.createElement('div')12 })13 document.body.appendChild(instance.$el)14 instance.componentName = component15 } else {16 // 已经创建17 if (instance.visible) return18 instance.componentName = component19 instance.visible = true20 }21 },2223 close() {24 if (instance) {25 instance.visible = false26 }27 }28}29
复制代码组件
01<template>02 <div v-if='visible' class='my-model center-flex'>03 <div @click='close' ref='model' class='bg'></div>04 <div class='wrapper'>05 <component v-if='componentName' :is='componentName'></component>06 </div>07 </div>08</template>0910<script>11 export default {12 data() {13 return {14 visible: true,15 componentName: ''16 }17 },18 methods: {19 close() {20 this.visible = false21 }22 },23 mounted() {24 this.$nextTick(() => {25 this.$refs.model.ontouchmove = (e) => {26 e.preventDefault()27 }28 })29 }30 }31</script>3233<style lang='scss' scoped>34 .my-model {35 position: fixed;36 left: 0;37 top: 0;38 width: 100%;39 height: 100%;40 }4142 .bg {43 display: block;44 width: 100%;45 height: 100%;46 background: rgba(0, 0, 0, 0.3);47 position: absolute;48 left: 0;49 top: 0;50 }5152 .wrapper {53 position: relative;54 z-index: 1;55 background: white;56 }57</style>58
复制代码