1- import { createVNode , render , ref , VNode } from "vue" ;
1+ import { createVNode , render , ref , VNode , isVNode } from "vue" ;
22import type { MessageQueue } from "./message" ;
33import MessageConstructor from "./message.vue" ;
44let seed = 1 ;
55const zIndex = ref ( 2000 ) ;
66const instances : MessageQueue = [ ] ;
77
88const message = function ( options = { } ) {
9+ if ( typeof options === "string" || isVNode ( options ) ) {
10+ options = { message : options } ;
11+ }
12+
913 let verticalOffset = 20 ;
1014 instances . forEach ( ( { vm } ) => {
1115 verticalOffset += ( vm . el ?. offsetHeight || 0 ) + 16 ;
@@ -21,29 +25,42 @@ const message = function (options = {}) {
2125 onClose : ( ) => {
2226 close ( id , userOnClose ) ;
2327 } ,
24- } ;
28+ } as any ;
2529
2630 let appendTo : HTMLElement | null = document . body ;
31+ if ( options . appendTo instanceof HTMLElement ) {
32+ appendTo = options . appendTo ;
33+ } else if ( typeof options . appendTo === "string" ) {
34+ appendTo = document . querySelector ( options . appendTo ) ;
35+ }
36+ // should fallback to default value with a warning
37+ if ( ! ( appendTo instanceof HTMLElement ) ) {
38+ throw new Error (
39+ "JwMessage the appendTo option is not an HTMLElement. Falling back to document.body."
40+ ) ;
41+ appendTo = document . body ;
42+ }
2743
2844 const container = document . createElement ( "div" ) ;
2945 container . className = `container_${ id } ` ;
30- const vm = createVNode ( MessageConstructor , props , null ) ;
3146
32- // clean message element preventing mem leak
47+ const message = props . message ;
48+ const vm = createVNode (
49+ MessageConstructor ,
50+ props ,
51+ isVNode ( props . message ) ? { default : ( ) => message } : null
52+ ) ;
53+ // 清除消息元素以防止内存泄漏
3354 vm . props ! . onDestroy = ( ) => {
3455 render ( null , container ) ;
35- // since the element is destroy, then the VNode should be collected by GC as well
36- // we do not want cause any mem leak because we have returned vm as a reference to users
37- // so that we manually set it to false.
3856 } ;
3957
4058 render ( vm , container ) ;
4159 instances . push ( { vm } ) ;
4260 appendTo . appendChild ( container . firstElementChild ! ) ;
4361
4462 return {
45- // instead of calling the onClose function directly, setting this value so that we can have the full lifecycle
46- // for out component, so that all closing steps will not be skipped.
63+ // 不是直接调用 onClose 函数,而是设置这个值,这样我们就可以拥有完整的生命周期
4764 close : ( ) => ( ( vm . component ! . proxy as any ) . visible = false ) ,
4865 } ;
4966} ;
0 commit comments