在最近的项目中,使用了bootstrap-vue来开发,然而在实际的开发过程中却发现这个UI提供的组件并不能打到我们预期的效果,像alert、modal等组件每个页面引入就得重复引入,并不像element那样可以通过this. x x x 来 调 用 , 那 么 问 题 来 了 , 如 何 通 过 t h i s . xxx来调用,那么问题来了,如何通过this. xxx来调用,那么问题来了,如何通过this.xxx来调用起我们定义的组件或对我们所使用的UI框架的组件呢。

以bootstrap-vue中的Alert组件为例,分一下几步进行:

1、定义一个vue文件实现对原组件的再次封装

main.vue

<b-alert
class="alert-wrap pt-4 pb-4"
:show="isAutoClose"
:variant="type" dismissible
:fade="true"
@dismiss-count-down="countDownChanged"
@dismissed="dismiss"
>
{{msg}}
</b-alert>
</template>
<script>
export default {
/**
* 参考: https://bootstrap-vue.js.org/docs/components/alert
* @param {string|number} msg 弹框内容
* @param {tstring} type 弹出框类型 对应bootstrap-vue中variant 可选值有:'primary'、'secondary'、'success'、'danger'、'warning'、'info'、'light'、'dark'默认值为 'info'
* @param {boolean} autoClose 是否自动关闭弹出框
* @param {number} duration 弹出框存在时间(单位:秒)
* @param {function} closed 弹出框关闭,手动及自动关闭都会触发
*/
props: {
msg: {
type: [String, Number],
default: ''
},
type: {
type: String,
default: 'info'
},
autoClose: {
type: Boolean,
default: true
},
duration: {
type: Number,
default: 3
},
closed: {
type: Function,
default: null
}
},
methods: {
dismiss () {
this.duration = 0
},
countDownChanged (duration) {
this.duration = duration
}
},
computed: {
isAutoClose () {
if (this.autoClose) {
return this.duration
} else {
return true
}
}
},
watch: {
duration () {
if (this.duration === 0) {
if (this.closed) this.closed()
}
}
}
}
</script>
<style scoped>
.alert-wrap {
position: fixed;
width: 600px;
top: 80px;
left: 50%;
margin-left: -200px;
z-index: 2000;
font-size: 1.5rem;
}
</style>

这里主要就是对组件参数、回调事件的一些处理,与其他处理组件的情况没有什么区别

2、定义一个js文件挂载到Vue上,并和我们定义的组件进行交互

index.js

import Alert from './main.vue'
import Vue from 'vue'
let AlertConstructor = Vue.extend(Alert)
let instance
let seed = 1
let index = 2000
const install = () => {
Object.defineProperty(Vue.prototype, '$alert', {
get () {
let id = 'message_' + seed++
const alertMsg = options => {
instance = new AlertConstructor({
propsData: options
})
index++
instance.id = id
instance.vm = instance.$mount()
document.body.appendChild(instance.vm.$el)
instance.vm.$el.style.zIndex = index
return instance.vm
}
return alertMsg
}
})
}
export default install

其主要思想是通过调用这个方法给组件传值,然后append到body下

3、最后需要在main.js中use一下

import Alert from '@/components/alert/index'
Vue.use(Alert)

4、使用

this.$alert({msg: '欢迎━(*`∀´*)ノ亻!'})

5、confrim的封装也是一样的

main.vue

<template>
<b-modal
v-if="!destroy"
v-model="isShow"
title="温馨提示"
@change="modalChange"
@show="modalShow"
@shown="modalShown"
@hide="modalHide"
@hidden="modalHidden"
@ok="modalOk"
@cancel="modalCancel"
:centered="true"
:hide-header-close="hideHeaderClose"
:no-close-on-backdrop="noCloseOnBackdrop"
:no-close-on-esc="noCloseOnEsc"
:cancel-title="cancelTitle"
:ok-title="okTitle">
<p class="my-4">{{msg}}</p>
</b-modal>
</template>
<script>
export default {
/**
* 参考: https://bootstrap-vue.js.org/docs/components/modal
* @param {boolean} isShow 是否显示modal框
* @param {string|number} msg 展示内容
* @param {boolean} hideHeaderClose 是否展示右上角关闭按钮 默认展示
* @param {string} cancelTitle 取消按钮文字
* @param {string} okTitle 确定按钮文字
* @param {boolean} noCloseOnBackdrop 能否通过点击外部区域关闭弹框
* @param {boolean} noCloseOnEsc 能否通过键盘Esc按键关闭弹框
* @param {function} change 事件触发顺序: show -> change -> shown -> cancel | ok -> hide -> change -> hidden
* @param {function} show before modal is shown
* @param {function} shown modal is shown
* @param {function} hide before modal has hidden
* @param {function} hidden after modal is hidden
* @param {function} ok 点击'确定'按钮
* @param {function} cancel 点击'取消'按钮
* @param {Boolean} destroy 组件是否销毁 在官方并没有找到手动销毁组件的方法,只能通过v-if来实现
*/
props: {
isShow: {
type: Boolean,
default: true
},
msg: {
type: [String, Number],
default: ''
},
hideHeaderClose: {
type: Boolean,
default: false
},
cancelTitle: {
type: String,
default: '取消'
},
okTitle: {
type: String,
default: '确定'
},
noCloseOnBackdrop: {
type: Boolean,
default: true
},
noCloseOnEsc: {
type: Boolean,
default: true
},
change: {
type: Function,
default: null
},
show: {
type: Function,
default: null
},
shown: {
type: Function,
default: null
},
hide: {
type: Function,
default: null
},
hidden: {
type: Function,
default: null
},
ok: {
type: Function,
default: null
},
cancel: {
type: Function,
default: null
},
destroy: {
type: Boolean,
default: false
}
},
methods: {
modalChange () {
if (this.change) this.change()
},
modalShow () {
if (this.show) this.show()
},
modalShown () {
if (this.shown) this.shown()
},
modalHide () {
if (this.hide) this.hide()
},
modalHidden () {
if (this.hidden) this.hidden()
this.destroy = true
},
modalOk () {
if (this.ok) this.ok()
},
modalCancel () {
if (this.cancel) this.cancel()
}
}
}
</script>

index.js

import Confirm from './main.vue'
import Vue from 'vue'
let ConfirmConstructor = Vue.extend(Confirm)
let instance
let seed = 1
let index = 1000
const install = () => {
Object.defineProperty(Vue.prototype, '$confirm', {
get () {
let id = 'message_' + seed++
const confirmMsg = options => {
instance = new ConfirmConstructor({
propsData: options
})
index++
instance.id = id
instance.vm = instance.$mount()
document.body.appendChild(instance.vm.$el)
instance.vm.$el.style.zIndex = index
return instance.vm
}
return confirmMsg
}
})
}
export default install

最后

为了帮助大家让学习变得轻松、高效,给大家免费分享一大批资料,帮助大家在成为全栈工程师,乃至架构师的路上披荆斩棘。在这里给大家推荐一个前端全栈学习交流圈:866109386.欢迎大家进群交流讨论,学习交流,共同进步。

当真正开始学习的时候难免不知道从哪入手,导致效率低下影响继续学习的信心。

但最重要的是不知道哪些技术需要重点掌握,学习时频繁踩坑,最终浪费大量时间,所以有有效资源还是很有必要的。

最后祝福所有遇到瓶疾且不知道怎么办的前端程序员们,祝福大家在往后的工作与面试中一切顺利。