效果
实现
一、封装一个基础modal弹窗
- 新建一个messageBox组件
messageBox.vue
<template>
<div :class="['message-box', type]">
<div class="inner">
<header class="header">
<h1 class="title">{{title}}</h1>
<span class="close-btn" @click="hideMessageBox">x</span>
</header>
<div class="content" v-if="typeof content === 'function'">
<render-content />
</div>
<div v-else>
{{content}}
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue';
export default {
name: 'MessageBox',
props: {
type: {
type: String,
default: 'primary',
validator: (value) => {
return [
'primary',
'success',
'warn',
'danger',
].includes(value)
}
},
title: {
type: String,
default: 'This is title'
},
content: {
type: [String, Function],
default: 'This is content'
}
},
created () {
if (typeof this.content === 'function') {
Vue.component('render-content', {
render: this.content
})
}
},
data() {
return {
};
},
mounted() {
},
methods: {
hideMessageBox () {
this.$messageBox.hide (() => {
console.log('HIDE')
})
}
},
};
</script>
<style lang="less" scoped>
.message-box {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,.5);
.inner {
position: absolute;
top: 100px;
left: 50%;
width: 500px;
margin-left: -250px;
background-color: #fff;
box-shadow: 1px 3px 5px #ededed;
border-radius: 5px;
overflow: hidden;
.header {
height: 44px;
padding: 0 10px;
line-height: 44px;
box-sizing: border-box;
.title {
float: left;
font-size: 16px;
}
.close-btn {
font-size: 24px;
float: right;
cursor: pointer;
}
}
.content {
padding: 20px;
box-sizing: border-box;
}
}
&.primary {
header {
background-color: #1890ff;
color: #fff;
}
}
&.success {
header {
background-color: #52c41a;
color: #fff;
}
}
&.warn {
header {
background-color: #faad14;
color: #fff;
}
}
&.danger {
header {
background-color: #f51a27;
color: #fff;
}
}
}
</style>
content
做兼容,使其支持jsx
- 在components的index.js中导出
index.js
import MessageBox from '@/components/messageBox'
export {
MessageBox
}
- 在main.js中导入使用
import MessageBox from '@/components/messageBox'
Vue.use(MessageBox)
二、使用extend实现函数式封装
- messageBox/index.js
import MessageBox from './messageBox'
export default {
install (Vue) {
let _messageBox = null
const show = (props, callback) => {
console.log('这个是show方法props', props)
if (!_messageBox) {
// extent()中的{} 就是export default {} 中的内容
const MessageBox = Vue.extend({
render(h) {
return h('MessageBox', {props})
}
})
console.log('MessageBox', MessageBox)
// 与Vue构造函数是一样的
_messageBox = new MessageBox()
console.log('_MESSAGEBOX',_messageBox )
this.vm = _messageBox.$mount()
console.log('this.vm', this.vm)
// 挂在到body
document.body.appendChild(this.vm.$el)
callback && callback()
}
}
const hide = (props, callback) => {
console.log('这个是hide方法', props)
document.body.removeChild(this.vm.$el)
_messageBox.$destroy();
_messageBox = null
callback && callback()
}
const danger = (props, callback) => {
show({...props, type: 'danger'}, callback)
}
const warn = (props, callback) => {
show({...props, type: 'warn'}, callback)
}
const success = (props, callback) => {
show({...props, type: 'success'}, callback)
}
const info = (props, callback) => {
show({...props, type: 'primary'}, callback)
}
Vue.prototype.$messageBox = {
show,
hide,
danger,
warn,
success,
info
}
Vue.component(MessageBox.name, MessageBox)
}
}
这里的
install
方法在Vue.use
是会自动执行
三、在页面中使用
<template>
<div>
<button @click="openMessage">show</button>
<button @click="openMessageInfo">Info</button>
<button @click="openMessageSuccess">Success</button>
<button @click="openMessageDanger">Danger</button>
<button @click="openMessageWarn">Warn</button>
</div>
</template>
<script>
export default {
name: 'PriojectPage',
components: {},
data() {
return {
};
},
mounted() {
},
methods: {
openMessage () {
console.log('this.$messageBox', this.$messageBox)
this.$messageBox.show({
title: 'APP',
content: h => {
return h('div', {'class': 'inner-title'},
Array.apply(null, {length: 10}).map(() => ['This is content for App', h('div',{style: {color: '#ccc'}}, '换行了')])
)
},
type: 'primary'
})
},
openMessageInfo () {
this.$messageBox.info({
title: 'APP',
content: 'This is content for APP',
})
},
openMessageSuccess () {
this.$messageBox.success({
title: 'APP',
content: 'This is content for APP',
})
},
openMessageDanger () {
this.$messageBox.danger({
title: 'APP',
content: 'This is content for APP',
})
},
openMessageWarn () {
this.$messageBox.warn({
title: 'APP',
content: 'This is content for APP',
})
}
}
}
</script>
<style lang="less">
.inner-title {
color: red;
}
</style>