1- import { h , defineComponent , ref , onMounted , onBeforeUnmount , computed } from 'vue' ;
1+ import { h , defineComponent , ref , onMounted , onBeforeUnmount , watch , isRef , isReactive , toRaw } from 'vue' ;
22
33export function omiVueify (
44 tagName : string ,
@@ -28,22 +28,7 @@ export function omiVueify(
2828
2929 expose ( methods ) ;
3030
31- // 处理属性命名规则
32- const formatAttrs = computed ( ( ) =>
33- Object . fromEntries (
34- Object . entries ( attrs )
35- // 仅处理非事件
36- . filter ( ( [ key ] ) => ! key . match ( / ^ o n [ A - Z a - z ] / ) )
37- . map ( ( [ key , value ] ) => {
38- // 复杂类型 转驼峰
39- if ( value && typeof value === 'object' ) {
40- return [ kebabToCamel ( key ) , value ] ;
41- }
42- // 基本数据类型 转kebab-case
43- return [ camelToKebab ( key ) , value ] ;
44- } ) ,
45- ) ,
46- ) ;
31+ const formatAttrs = useUnwrapAndFormatAttrs ( attrs ) ;
4732
4833 // 处理事件监听
4934 const omiEvents = Object . keys ( attrs )
@@ -151,4 +136,52 @@ const camelToKebab = (omiEvent: string): string => {
151136 */
152137const kebabToCamel = ( str : string ) : string => {
153138 return str . replace ( / - ( [ a - z ] ) / g, ( _match , p1 ) => p1 . toUpperCase ( ) ) ;
154- }
139+ }
140+
141+ const deepUnwrap = ( val : any ) : any => {
142+ if ( isRef ( val ) ) return deepUnwrap ( val . value ) ;
143+ if ( isReactive ( val ) ) val = toRaw ( val ) ;
144+ if ( Array . isArray ( val ) ) return val . map ( deepUnwrap ) ;
145+ if ( val && typeof val === 'object' ) {
146+ const obj : Record < string , any > = { } ;
147+ for ( const k in val ) obj [ k ] = deepUnwrap ( val [ k ] ) ;
148+ return obj ;
149+ }
150+ return val ;
151+ } ;
152+
153+ /**
154+ * 将 attrs 里的非事件属性递归解包为普通对象,且驼峰kebab命名兼容
155+ */
156+ const useUnwrapAndFormatAttrs = ( attrs : Record < string , any > ) => {
157+ const unwraped = ref ( { } ) ;
158+
159+ // watch keys变化,自动维护监听
160+ watch (
161+ ( ) => Object . entries ( attrs ) ,
162+ ( entries ) => {
163+ const result : Record < string , any > = { } ;
164+ entries . forEach ( ( [ key , value ] ) => {
165+ if ( ! key . match ( / ^ o n [ A - Z a - z ] / ) ) {
166+ // 对象类型转驼峰,基本类型转kebab
167+ let finalKey = key ;
168+ let finalValue = value ;
169+ if ( isRef ( value ) || isReactive ( value ) ) {
170+ finalValue = deepUnwrap ( value ) ;
171+ }
172+
173+ if ( finalValue && typeof finalValue === 'object' ) {
174+ finalKey = kebabToCamel ( key ) ;
175+ } else {
176+ finalKey = camelToKebab ( key ) ;
177+ }
178+ result [ finalKey ] = finalValue ;
179+ }
180+ } ) ;
181+ unwraped . value = result ;
182+ } ,
183+ { immediate : true , deep : true } ,
184+ ) ;
185+
186+ return unwraped ;
187+ } ;
0 commit comments