用法特殊性,這類組件不需要在父組件‘template’中引用。可以直接調用。
this.$notify({
title: '提示',
message: '這是一條不會自動關閉的消息',
duration: 0
});
1.顯示出彈窗
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而存在的,比如上文提到的 顯示的位置管理,還有關閉的管理。
2.顯示出不同內容
調用this.$notify(‘xxx’),這樣’xxx’就可以顯示出來。
2.1參數爲options對象
使用方式如下
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,
};
2.2參數爲 VNode
使用方式如下
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()
3.notification移除
3.1當notification消失後,過段時間將被移除;
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
});