用法特殊性,这类组件不需要在父组件‘template’中引用。可以直接调用。
this.$notify({
title: '提示',
message: '这是一条不会自动关闭的消息',
duration: 0
});
main.js文件
//1.main.vue是弹出框的组件
import Main from './main.vue';
//2.继承得到main.vue的构造器。Vue.extend用法见vue文档
const NotificationConstructor = Vue.extend(Main);
//3. this.$notify的实际调用对象
const Notification = function(options) {
if (Vue.prototype.$isServer) return;
options = options || {};
const userOnClose = options.onClose;
const id = 'notification_' + seed++;
const position = options.position || 'top-right';
/* 4. 通过函数参数传入的options,通过2.得到的构造器新建一个对象,
这里的options对象与main.vue中的按混入形式存在。*/
instance = new NotificationConstructor({
data: options
});
instance.id = id;
// 5.见vue文档。$mount的部分。$mount()、Vue.extend(xxx)配合使用。
// 当$mount()没有传入id选择器时,在文档之外渲染并且随后挂载
instance.$mount();
document.body.appendChild(instance.$el);
// 6.到这里就完成main.vue的显示,下面是对多个对象同时显示时,位置的管理。
instance.visible = true;
instance.dom = instance.$el;
instance.dom.style.zIndex = PopupManager.nextZIndex();
// 对显示的位置进行管理,避免重叠
let verticalOffset = options.offset || 0;
// 按逻辑,这里filter得到的,必然是一个或0个。一般的,如果是0,if判断跳过foreach。
// 这里的的写法算是一种简化,让forEach自行判断。
instances.filter(item => item.position === position).forEach(item => {
verticalOffset += item.$el.offsetHeight + 16;
});
verticalOffset += 16;
instance.verticalOffset = verticalOffset;
instances.push(instance);
return instance;
};
main.js的是为了管理这些main.vue而存在的,比如上文提到的 显示的位置管理,还有关闭的管理。
调用this.$notify(‘xxx’),这样’xxx’就可以显示出来。
使用方式如下
this.$notify({
title: '提示',
message: '这是一条不会自动关闭的消息',
duration: 0
});
main.js文件
把options对象中的属性 合并 到vue的data中。message、title和duration将覆盖main.vue中的data。
instance = new NotificationConstructor({
data: options
});
main.vue文件
1.如果message是普通字符串,直接显示
2.message是html格式字符串,需要设置dangerouslyUseHTMLString=true, v-html="message"将输出这段html代码
<div class="el-notification__content" v-show="message">
<slot>
<p v-if="!dangerouslyUseHTMLString">{{ message }}</p>
<p v-else v-html="message"></p>
</slot>
</div>
data() {
return {
title: '',
message: '',
dangerouslyUseHTMLString: false,
duration: 3000,
};
使用方式如下
const h = this.$createElement;
this.$notify({
title: '标题名称',
message: h('i', { style: 'color: teal'}, '这是提示示文案')
});
main.js文件
$slots.default是插槽的默认对象,非具名插槽都会显示到default中,所以defalut为一个数组。
想修改插槽中的内容,如下,可对$slots.default重新赋值。赋值后内容并不会显示出来,需要触发一次渲染。
if (isVNode(options.message)) {
instance.$slots.default = [options.message];
options.message = 'REPLACED_BY_VNODE';
}
options.message = ‘REPLACED_BY_VNODE’;引发一次触发渲染。
因为main.vue中v-show=‘message’,message 的改变触发渲染。
<div class="el-notification__content" v-show="message">
<slot>
<p v-if="!dangerouslyUseHTMLString">{{ message }}</p>
<p v-else v-html="message"></p>
</slot>
</div>
message不光从’’(空字符,false),变成字符串‘REPLACED_BY_VNODE’(true)触发的。message任意的改变值都会触发,只要与之前不同。
$slots.default 赋值后,调用官方提供的vm.$forceUpdate(),将刷新 当前组件 和 插槽 ,不刷新 当前组件 的 子组件(见vue文档),这种方式效率低
this.$slots.default = [vnode]
vm.$forceUpdate()
main.vue文件
需要用到的字段,duration为3秒
data() {
return {
visible: false,
duration: 3000,
showClose: true,
// 属于main.js的回调函数
onClose: null,
onClick: null,
closed: false,
timer: null,
position: 'top-right'
};
钩子函数,setTimeout超时duration后关闭调用close()
mounted() {
if (this.duration > 0) {
this.timer = setTimeout(() => {
if (!this.closed) {
this.close();
}
}, this.duration);
}
document.addEventListener('keydown', this.keydown);
},
这里this.onClose()的是,由main.js(notification管理器)传入的 一个回调函数
close() {
this.closed = true;
if (typeof this.onClose === 'function') {
this.onClose();
}
},
main.js文件
options.onClose 定义回调函数。new NotificationConstructor()将把onClose混入到instance(notification对象)中
options.onClose = function() {
Notification.close(id, userOnClose);
};
instance = new NotificationConstructor({
data: options
});