diff --git a/packages/omi-vueify/src/index.ts b/packages/omi-vueify/src/index.ts index 220bd51fe..4df02b450 100644 --- a/packages/omi-vueify/src/index.ts +++ b/packages/omi-vueify/src/index.ts @@ -1,4 +1,4 @@ -import { h, defineComponent, ref, onMounted, onBeforeUnmount, watch, isRef, isReactive, toRaw } from 'vue'; +import { h, defineComponent, ref, shallowRef, onMounted, onBeforeUnmount, watch, isRef, isReactive, toRaw } from 'vue'; export function omiVueify( tagName: string, @@ -164,7 +164,7 @@ const deepUnwrap = (val: any): any => { * 将 attrs 里的非事件属性递归解包为普通对象,且驼峰kebab命名兼容 */ const useUnwrapAndFormatAttrs = (attrs: Record) => { - const unwraped = ref({}); + const unwraped = shallowRef>({}); // watch keys变化,自动维护监听 watch( diff --git a/packages/omi-vueify/test/vueify.test.jsx b/packages/omi-vueify/test/vueify.test.jsx index 93fe087b1..117cbc5f6 100644 --- a/packages/omi-vueify/test/vueify.test.jsx +++ b/packages/omi-vueify/test/vueify.test.jsx @@ -1,5 +1,5 @@ import { render } from '@testing-library/vue' -import { defineComponent, nextTick, Fragment, h } from 'vue' +import { defineComponent, nextTick, Fragment, h, reactive, isProxy } from 'vue' import { define, Component, h as hOmi } from 'omi' import { omiVueify } from '../src' @@ -380,6 +380,31 @@ describe('methods', () => { }) describe('complex data types', () => { + it('should pass plain objects to Omi without creating Vue proxies', async () => { + const TestVue = omiVueify(nodeName, { methodNames: [] }) + const items = [{ name: 'test.txt' }] + const complexData = { value: 'plain', items } + + const { container } = render(defineComponent({ + components: { TestComponent: TestVue }, + template: '', + setup() { + return { complexData } + } + })) + + await nextTick() + + const webComponent = container.querySelector(nodeName) + const receivedData = webComponent.props.complexData + + expect(isProxy(receivedData)).toBe(false) + expect(receivedData).toBe(complexData) + expect(receivedData.items).toBe(items) + Object.freeze(receivedData.items) + expect(() => receivedData.items[0]).not.toThrow() + }) + it('should properly handle complex data types', async () => { class ComplexDataComponent extends Component { static propTypes = { @@ -425,6 +450,40 @@ describe('complex data types', () => { expect(retrievedData.nested.value).toBe('test') expect(retrievedData.array).toEqual([1, 2, 3]) }) + + it('should keep reactive nested updates without proxying values passed to Omi', async () => { + const TestVue = omiVueify(nodeName, { methodNames: [] }) + const complexData = reactive({ + value: 'initial', + nested: { count: 0 } + }) + + const { container } = render(defineComponent({ + components: { TestComponent: TestVue }, + template: '', + setup() { + return { complexData } + } + })) + + await nextTick() + + const webComponent = container.querySelector(nodeName) + const initialData = webComponent.props.complexData + expect(isProxy(initialData)).toBe(false) + expect(isProxy(initialData.nested)).toBe(false) + + complexData.nested.count++ + await nextTick() + await Promise.resolve() + + const updatedData = webComponent.props.complexData + expect(updatedData).not.toBe(initialData) + expect(updatedData.nested.count).toBe(1) + expect(isProxy(updatedData)).toBe(false) + expect(isProxy(updatedData.nested)).toBe(false) + }) + }) describe('dynamic prop updates', () => {