用Vue.extend()来做一个全局提示组件
程序员文章站
2024-03-04 16:58:05
...
相信很多人用vuejs构建单页应用时都会用到一些全局方法,比如发ajax请求时喜欢用axios挂载到vue原型上,如下:
// 1 引入vue和axios
import Vue from 'vue'
import axios from 'axios'
// 2 对axios的一些封装
// code ...
// 3 然后挂载到原型上
Vue.prototype.$axios = axios
用的时候就直接上this.$axios
// 用axios.get()方法可以这样用
this.$axios.get()
这样确实方便,不用每个用到axios的组件都去引入
类似如此,当我们要用到一些操作dom的方法时要怎么做呢,上面的例子纯属js的封装,没有涉及到dom;下面我用一个全局提示组件为例,为大家演示一遍如何封装一个包含操作dom的的全局组件的,步骤主要有3步:
1, 在componenets 目录下新建一个Message.vue组件
<template>
<div class="messMessage" :id="messId" v-if="isMessage" >
<div ref="messMessage" :class="['messageBox', type,isMesSHow?'messageBoxShow':'messageBoxHide']"
:style="{'textAlign':align,width:width,padding:padding,borderRadius:borderRadius,background,background,color:color}">
<!--提示的ICON-->
<mgn-icon class="pc" :style="[iconData,{marginTop:-(iconStyle.fontSize.split('px')[0]/2)+0.5+'px'}]" :iconClass="iconStyle.name"></mgn-icon>
<!--message内容-->
<p v-html="message" :style="contStyles"></p>
<!--关闭安钮-->
<span class="messageClose pc"
:style="{marginTop:-(closeIconStyle.fontSize.split('px')[0]/2)+'px'}"
@click="messClose" v-if="isCloseIcon">
<mgn-icon :style="closeIcon" :iconClass="closeIconStyle.name"></mgn-icon>
</span>
</div>
</div>
</template>
<script type="text/ecmascript-6">
import mgnIcon from '@/components/pcComponents/icon'
export default {
data () {
return {
// 组件内参数
messId: (Math.random() + '').substring(3),
isTrue: true,
isMessage: false,
// 以下为传入
// icon图标样式
iconStyle: {
color: '',
fontSize: '',
name: ''
},
// icon组件
iconData: {},
// 关闭icon
closeIcon: {},
// 内容对齐方式
align: 'left',
// 弹框宽度
width: '240px',
// 弹框内边距
padding: '14px, 26px, 14px, 14px',
// 弹框圆角
borderRadius: '4px',
// 弹框背景颜色
background: '',
// 弹框字体颜色
color: '',
// 关闭icon
isCloseIcon: true,
// 关闭icon样式
closeIconStyle: {
color: '',
fontSize: '',
name: 'iconclose-line'
},
// 是否开自动关闭
isAutoClose: true,
// 信息类型 默认样式 info 成功 success 警告 warning 错误 error
type: 'define',
// 提示的消息内容
message: '-',
// 提示内容文字样式
contStyles: {
color: '',
fontSize: '14px'
},
// 自动关闭的时间(毫秒)
duration: 2000,
// 显示组件
isMesSHow: true
}
},
methods: {
// 调用事件
messOpen (options) {
this.isMessage = true
this.$nextTick(() => {
// 参数处理
if (!this.iconStyle.name) {
switch (this.type) {
case 'success':
this.iconStyle.name = 'iconcheck-fill'
break
case 'warning':
this.iconStyle.name = 'icongantan'
break
case 'error':
this.iconStyle.name = 'iconclose-fill'
break
case 'info':
this.iconStyle.name = 'iconsigh-fill'
break
}
}
for (const key in this.inputDefault) {
if (key.indexOf('Of') !== -1) {
let arr = key.split('Of')
this[arr[0]][this.titleCase(arr[1])] = this.inputDefault[key]
}
}
this.iconData = {
fontSize: this.iconStyle.fontSize,
color: this.iconStyle.color
}
this.closeIcon = {
fontSize: this.closeIconStyle.fontSize,
color: this.closeIconStyle.color
}
this.iconStyle.fontSize = this.iconStyle.fontSize || '18px'
this.closeIconStyle.fontSize = this.closeIconStyle.fontSize || '16px'
this.contStyles.fontSize = this.contStyles.fontSize || '14px'
this.contStyles.marginLeft = this.iconStyle.name ? '26px' : 0
this.contStyles.marginRight = '26px'
this.isMesSHow = true
let _this = this
this.$nextTick(() => {
if (_this.isAutoClose) {
setTimeout(function () {
_this.isMesSHow = false
// 清除dom结构
_this.clearDom()
}, _this.duration)
}
})
})
},
// 转换首字母大写
titleCase (name) {
return name.charAt(0).toLowerCase() + name.slice(1)
},
// 关闭事件
messClose () {
this.isMesSHow = false
this.clearDom()
},
// 清除dom结构
clearDom () {
let _this = this
setTimeout(function () {
var self = document.getElementById(_this.messId)
if (self)document.body.removeChild(self)
}, 280)
}
},
components: {
mgnIcon
}
}
</script>
<style scoped lang="less" rel="stylesheet/less">
@import "../../common/less/base";
.messMessage {
.pr();
.l(1);
@keyframes showAni {
0% {
opacity: 0;
top: 0px;
}
100% {
opacity: 1;
top: 30px;
}
}
@keyframes showAni2 {
0% {
opacity: 1;
top: 30px;
}
100% {
opacity: 0;
top: 0px;
}
}
.pc{
.pa();
.pos-t(50%);
}
.messageBoxShow{
animation: showAni 0.3s ease;
}
.messageBoxHide{
animation: showAni2 0.3s ease;
}
.messageBox {
.ml(-119px);
.w(240px);
.p(14px, 26px, 14px, 14px);
.radius(4px);
.border-box();
.pf();
.zindex(9999999) !important;
.pos-t(30px);
.pos-l(50%);
p {
.f(14px);
.i-block();
.ml(10px);
.mr(15px);
}
.messageClose {
.pa();
.pos-r(15px);
.pointer();
.fc(#c0c4cc);
.iconfont{
.left();
.f(14px);
}
}
}
.info,
.success,
.warning,
.error{
.iconfont {
.f(13px);
}
}
.messageCont {
.pa();
.pos-t(50%);
}
// 默认样式
.define {
.bgc(#edf2fc);
.bs(1px, solid, #ebeef5);
.fc(#909399);
.messageCont {
.fc(#909399) !important;
}
}
// 提示
.info {
.bgc(#edf2fc);
.bs(1px, solid, #ebeef5);
.fc(#909399);
.messageCont {
.fc(#909399) !important;
}
}
// 成功
.success {
.bgc(#f0f9eb);
.bs(1px, solid, #e1f3d8);
.fc(#67c23a);
.messageCont {
.fc(#67c23a) !important;
}
}
// 警告
.warning {
.bgc(#fdf6ec);
.bs(1px, solid, #faecd8);
.fc(#e6a23c) !important;
.messageCont {
.fc(#e6a23c) !important;
}
}
// 错误
.error {
.bgc(#fef0f0);
.bs(1px, solid, #fde2e2);
.fc(#f56c6c);
.messageCont {
.fc(#f56c6c) !important;
}
}
}
</style>
2在项目里创建一个js文件
import messageVue from '../../components/pcComponents/message'
const messageBox = {
install (Vue) {
const MessageBoxInstance = Vue.extend(messageVue)
let currentMsg
const initInstance = () => {
// 实例化vue实例
currentMsg = new MessageBoxInstance()
let msgBoxEl = currentMsg.$mount().$el
document.body.appendChild(msgBoxEl)
}
// 在Vue的原型上添加实例方法,以全局调用
Vue.prototype.$message = function (options) {
initInstance()
currentMsg._data = Object.assign(currentMsg._data, options)
return currentMsg.messOpen()
}
}
}
export default messageBox
3,在main.js中引入你创建的js文件,以插件形式安装
import Vue from 'vue'
import message from './common/js/mesShow'
Vue.use(message)
最后,当你需要用的时候就直接,特别适合在ajax回调函数里面用来提示
this.$message({
type: 'success',
message: '替换icon图标',
iconStyle: {
name: 'icondredge-circle',
color: '#ff7c10',
fontSize: '14px'
}
下一篇: springmvc 参数绑定总结