1
- /* eslint-disable no-undef */
2
- import { h , isVNode , createTextVNode , VNode , ComponentPublicInstance , Slots } from 'vue' ;
3
- import { TNode } from '../common' ;
4
-
5
- // 组件render属性的ts类型
6
- type RenderTsTypesSimple = string | number | boolean ;
7
- type RenderTsTypesObject = Record < string , any > | Array < any > ;
8
- type RenderTsTypes = VNode | TNode | RenderTsTypesSimple | RenderTsTypesObject ;
9
-
10
- // 定义组件内容的渲染方式
11
- enum RenderWay {
12
- Text = 'text' ,
13
- JsonString = 'jsonstring' ,
14
- VNode = 'vnode' ,
15
- Unknown = 'unknown' ,
16
- }
17
-
18
- /**
19
- * 根据传入的值(对象),判断渲染该值(对象)的方式
20
- * @param value 传入的值(对象)
21
- */
22
- const getValueRenderWay = ( value : RenderTsTypes ) : RenderWay => {
23
- // 简单类型
24
- if ( [ 'string' , 'number' , 'boolean' ] . includes ( typeof value ) ) return RenderWay . Text ;
25
- // 复杂对象
26
- if ( typeof value === 'object' ) {
27
- // 虚拟dom对象
28
- if ( isVNode ( value ) ) {
29
- return RenderWay . VNode ;
30
- }
31
- // 其他复杂对象或数组
32
- return RenderWay . JsonString ;
33
- }
34
- // 未知类型(兜底)
35
- return RenderWay . Unknown ;
36
- } ;
37
-
38
- // 通过template的方式渲染TNode
39
- export const RenderTNodeTemplate = ( props : { render : Function ; params : Record < string , any > } ) => {
40
- const { render, params } = props ;
41
- const renderResult = typeof render === 'function' ? render ( h , params ) : render ;
42
- const renderWay = getValueRenderWay ( renderResult ) ;
43
-
44
- const renderText = ( c : RenderTsTypesSimple | RenderTsTypesObject ) => createTextVNode ( `${ c } ` ) ;
45
- const renderMap = {
46
- [ RenderWay . Text ] : ( c : RenderTsTypesSimple ) => renderText ( c ) ,
47
- [ RenderWay . JsonString ] : ( c : RenderTsTypesObject ) => renderText ( JSON . stringify ( c , null , 2 ) ) ,
48
- [ RenderWay . VNode ] : ( c : VNode ) => c ,
49
- } ;
50
-
51
- return renderMap [ renderWay ] ? renderMap [ renderWay ] ( renderResult ) : h ( null ) ;
52
- } ;
53
-
54
- interface JSXRenderContext {
55
- defaultNode ?: VNode ;
56
- params ?: Record < string , any > ;
57
- }
1
+ import { h , ComponentPublicInstance } from 'vue' ;
2
+ import isFunction from 'lodash/isFunction' ;
3
+ import isEmpty from 'lodash/isEmpty' ;
4
+ import { getDefaultNode , getParams , OptionsType } from '../hooks/tnode' ;
58
5
59
6
/**
60
7
* 通过JSX的方式渲染 TNode,props 和 插槽同时处理,也能处理默认值为 true 则渲染默认节点的情况
@@ -66,29 +13,30 @@ interface JSXRenderContext {
66
13
* @example renderTNodeJSX(this, 'closeBtn', { defaultNode: <close-icon />, params })。 params 为渲染节点时所需的参数
67
14
*/
68
15
69
- export const renderTNodeJSX = (
70
- instance : ComponentPublicInstance ,
71
- name : string ,
72
- options ?: Slots | JSXRenderContext | JSX . Element ,
73
- ) => {
74
- const params = typeof options === 'object' && 'params' in options ? options . params : null ;
75
- const defaultNode = typeof options === 'object' && 'defaultNode' in options ? options . defaultNode : options ;
16
+ export const renderTNodeJSX = ( instance : ComponentPublicInstance , name : string , options ?: OptionsType ) => {
17
+ // assemble params && defaultNode
18
+ const params = getParams ( options ) ;
19
+ const defaultNode = getDefaultNode ( options ) ;
20
+
21
+ // 处理 props 类型的Node
76
22
let propsNode ;
77
23
if ( name in instance ) {
78
24
propsNode = instance [ name ] ;
79
25
}
26
+
27
+ // propsNode 为 false 不渲染
80
28
if ( propsNode === false ) return ;
81
29
82
30
// 同名优先处理插槽
83
31
if ( instance . $slots [ name ] ) {
84
32
return instance . $slots [ name ] ( params ) ;
85
33
}
34
+ if ( isFunction ( propsNode ) ) return propsNode ( h , params ) ;
35
+
86
36
if ( propsNode === true && defaultNode ) {
87
37
return instance . $slots [ name ] ? instance . $slots [ name ] ( params ) : defaultNode ;
88
38
}
89
- if ( typeof propsNode === 'function' ) return propsNode ( h , params ) ;
90
- const isPropsEmpty = [ undefined , params , '' ] . includes ( propsNode ) ;
91
- if ( isPropsEmpty && instance . $slots [ name ] ) return instance . $slots [ name ] ( params ) ;
39
+
92
40
return propsNode ;
93
41
} ;
94
42
@@ -100,12 +48,8 @@ export const renderTNodeJSX = (
100
48
* @example renderTNodeJSX(this, 'closeBtn', <close-icon />)。this.closeBtn 为空时,则兜底渲染 <close-icon />
101
49
* @example renderTNodeJSX(this, 'closeBtn', { defaultNode: <close-icon />, params }) 。params 为渲染节点时所需的参数
102
50
*/
103
- export const renderTNodeJSXDefault = (
104
- vm : ComponentPublicInstance ,
105
- name : string ,
106
- options ?: Slots | JSXRenderContext | JSX . Element ,
107
- ) => {
108
- const defaultNode = typeof options === 'object' && 'defaultNode' in options ? options . defaultNode : options ;
51
+ export const renderTNodeJSXDefault = ( vm : ComponentPublicInstance , name : string , options ?: OptionsType ) => {
52
+ const defaultNode = getDefaultNode ( options ) ;
109
53
return renderTNodeJSX ( vm , name , options ) || defaultNode ;
110
54
} ;
111
55
@@ -119,17 +63,15 @@ export const renderTNodeJSXDefault = (
119
63
* @example renderContent(this, 'default', 'content', '我是默认内容')
120
64
* @example renderContent(this, 'default', 'content', { defaultNode: '我是默认内容', params })
121
65
*/
122
- export const renderContent = (
123
- vm : ComponentPublicInstance ,
124
- name1 : string ,
125
- name2 : string ,
126
- options ?: VNode | JSXRenderContext | JSX . Element ,
127
- ) => {
128
- const params = typeof options === 'object' && 'params' in options ? options . params : null ;
129
- const defaultNode = typeof options === 'object' && 'defaultNode' in options ? options . defaultNode : options ;
66
+ export const renderContent = ( vm : ComponentPublicInstance , name1 : string , name2 : string , options ?: OptionsType ) => {
67
+ const params = getParams ( options ) ;
68
+ const defaultNode = getDefaultNode ( options ) ;
69
+
130
70
const toParams = params ? { params } : undefined ;
71
+
131
72
const node1 = renderTNodeJSX ( vm , name1 , toParams ) ;
132
73
const node2 = renderTNodeJSX ( vm , name2 , toParams ) ;
133
- const r = [ undefined , null , '' ] . includes ( node1 ) ? node2 : node1 ;
134
- return [ undefined , null , '' ] . includes ( r ) ? defaultNode : r ;
74
+
75
+ const res = isEmpty ( node1 ) ? node2 : node1 ;
76
+ return isEmpty ( res ) ? defaultNode : res ;
135
77
} ;
0 commit comments