1 组件核心流程图
2 具体分析流程步骤(Message)
- 创建Message.vue 组件
- 核心配置参数
- visible 代表弹框是否显示与隐藏
- message 消息提示内容
- duration 弹框显示的时间
- closed 关闭 与watch 进行结合,用于监听 visible 的改变
- 定义构造函数
let MessageConstructor = Vue.extend(Main); // 形成指定组件的构造函数
instance = new MessageConstructor({
data: options //接收消息弹框参数
});
instance.$mount(); // 通过将实例进行挂载 可以得到 $el
document.body.appendChild(instance.$el); // 将组件中的元素添加到body元素中
instance.visible = true; // 同时组件实例中的 visible 改变 进行显示
return instance; // 返回组件
- 实例的挂在会触发 组件中 mounted 函数的执行
- 开始执行指定时间,会自动关闭弹框
- 关闭弹框时,由于watch的监听,会改变visible 状态
- 通过transition 嵌套的动画,也会 触发离开的事件的调用handleAfterLeave
- 将当前组件从Vue 实例中 销毁,同时从父节点中移除组件中的元素
<template>
<transition name="el-message-fade" @after-leave="handleAfterLeave">
<div
:class="[
'el-message',
type && !iconClass ? `el-message--${ type }` : '',
center ? 'is-center' : '',
showClose ? 'is-closable' : '',
customClass
]"
:style="positionStyle"
v-show="visible"
@mouseenter="clearTimer"
@mouseleave="startTimer"
role="alert">
<i :class="iconClass" v-if="iconClass"></i>
<i :class="typeClass" v-else></i>
<slot>
<p v-if="!dangerouslyUseHTMLString" class="el-message__content">{{ message }}</p>
<p v-else v-html="message" class="el-message__content"></p>
</slot>
<i v-if="showClose" class="el-message__closeBtn el-icon-close" @click="close"></i>
</div>
</transition>
</template>
<script type="text/babel">
const typeMap = {
success: 'success',
info: 'info',
warning: 'warning',
error: 'error'
};
export default {
data() {
return {
visible: false,
message: '',
duration: 3000,
type: 'info',
iconClass: '',
customClass: '',
onClose: null,
showClose: false,
closed: false,
verticalOffset: 20,
timer: null,
dangerouslyUseHTMLString: false,
center: false
};
},
computed: {
typeClass() {
return this.type && !this.iconClass
? `el-message__icon el-icon-${ typeMap[this.type] }`
: '';
},
positionStyle() {
return {
'top': `${ this.verticalOffset }px`
};
}
},
watch: {
closed(newVal) {
if (newVal) {
this.visible = false;
}
}
},
methods: {
handleAfterLeave() {
this.$destroy(true);
this.$el.parentNode.removeChild(this.$el);
},
close() {
this.closed = true;
if (typeof this.onClose === 'function') {
this.onClose(this);
}
},
clearTimer() {
clearTimeout(this.timer);
},
startTimer() {
if (this.duration > 0) {
this.timer = setTimeout(() => {
if (!this.closed) {
this.close(); // 执行一段时间后,会进行关闭
}
}, this.duration);
}
},
keydown(e) {
if (e.keyCode === 27) { // esc关闭消息
if (!this.closed) {
this.close();
}
}
}
},
mounted() {
this.startTimer(); // 开启定时器,由instance.$mount() 触发
document.addEventListener('keydown', this.keydown);
},
beforeDestroy() {
document.removeEventListener('keydown', this.keydown);
}
};
</script>
3 手写简易版
3.1 概念解释
extend:Vue 实例使用的根 DOM 元素。
propsData: 配置组件中的 props 接收的值, 相当于父传子的一种方式
- 限制:只用于 new 创建的实例中。
- 详细:创建实例时传递 props。主要作用是方便测试
var Comp = Vue.extend({
props: ['msg'],
template: '<div>{{ msg }}</div>'
})
var vm = new Comp({
propsData: {
msg: 'hello'
}
vm.$mount( [elementOrSelector] )
var Comp = Vue.extend({
props: ['msg'],
template: '<div>{{ msg }}</div>'
})
var vm = new Comp({
propsData: {
msg: 'hello'
}
})
3.2 创建create 工具函数
export default function create (Comp, props) {
const Ctor = Vue.extend(Comp) //创建 组件的构造函数
const intance = new Ctor({ // 创建组件的实例
propsData: props // 配置组件的参数
})
intance.$mount() // 获取 $el // 组件实例挂载
document.body.appendChild(intance.$el) // 组件的根元素以及内容添加到body
intance.remove = () => { // 往组件实例中添加 销毁 和 移除元素
intance.$destroy()
document.body.removeChild(intance.$el)
}
return intance // 返回组件实例
}
3.3 Vue实例中添加方法
import create from './utils/create'
import HuiNotice from './components/HuiNotice.vue'
Vue.prototype.$notice = (props) => {
const comp = create(HuiNotice, props)
comp.show()
return comp
}
3.4 登录校验未通过进行使用
onLogin () {
// console.log(11)
const formInstance = this.$refs.form
formInstance.validate((vaild) => {
if (vaild) {
console.log('校验通过')
} else {
console.log('校验没有通过')
// create(HuiNotice, {
// title: '温馨提示:',
// message: '校验没有通过',
// duration: 3000
// }).show()
this.$notice({
title: '温馨提示:',
message: '校验没有通过',
duration: 3000
})
}
})
}
},