Skip to content

Commit db1d3ec

Browse files
authored
Merge pull request #992 from LzhengH/fix/vueify-reactive
fix: 修复vueify中遇到reactive类型参数无法响应式的问题
2 parents c29511a + bbebedb commit db1d3ec

File tree

1 file changed

+51
-18
lines changed

1 file changed

+51
-18
lines changed

packages/omi-vueify/src/index.ts

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { h, defineComponent, ref, onMounted, onBeforeUnmount, computed } from 'vue';
1+
import { h, defineComponent, ref, onMounted, onBeforeUnmount, watch, isRef, isReactive, toRaw } from 'vue';
22

33
export 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(/^on[A-Za-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
*/
152137
const 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(/^on[A-Za-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

Comments
 (0)