function locateNonHydratedAsyncRoot(
instance: ComponentInternalInstance,
): ComponentInternalInstance | undefined {
- const subComponent = instance.subTree.component
+ const subComponent = instance.vapor ? null : instance.subTree.component
if (subComponent) {
if (subComponent.asyncDep && !subComponent.asyncResolved) {
return subComponent
-import { createVNode, defineComponent, h, renderSlot } from '@vue/runtime-dom'
+import {
+ createVNode,
+ defineComponent,
+ h,
+ nextTick,
+ ref,
+ renderSlot,
+ toDisplayString,
+ useModel,
+} from '@vue/runtime-dom'
import { makeInteropRender } from './_utils'
-import { createComponent, defineVaporComponent } from '../src'
+import {
+ applyTextModel,
+ child,
+ createComponent,
+ defineVaporComponent,
+ renderEffect,
+ setText,
+ template,
+} from '../src'
const define = makeInteropRender()
})
})
+ describe('v-model', () => {
+ test('basic work', async () => {
+ const VaporChild = defineVaporComponent({
+ props: {
+ modelValue: {},
+ modelModifiers: {},
+ },
+ emits: ['update:modelValue'],
+ setup(__props) {
+ const modelValue = useModel(__props, 'modelValue')
+
+ const n0 = template('<h1> </h1>')() as any
+ const n1 = template('<input>')() as any
+ const x0 = child(n0) as any
+ applyTextModel(
+ n1,
+ () => modelValue.value,
+ _value => (modelValue.value = _value),
+ )
+ renderEffect(() => setText(x0, toDisplayString(modelValue.value)))
+ return [n0, n1]
+ },
+ })
+
+ const { html, host } = define({
+ setup() {
+ const msg = ref('foo')
+ return () =>
+ h(VaporChild as any, {
+ modelValue: msg.value,
+ 'onUpdate:modelValue': (value: string) => {
+ msg.value = value
+ },
+ })
+ },
+ }).render()
+
+ expect(html()).toBe('<h1>foo</h1><input>')
+
+ const inputEl = host.querySelector('input')!
+ inputEl.value = 'bar'
+ inputEl.dispatchEvent(new Event('input'))
+
+ await nextTick()
+ expect(html()).toBe('<h1>bar</h1><input>')
+ })
+ })
+
describe('emit', () => {
test('emit from vapor child to vdom parent', () => {
const VaporChild = defineVaporComponent({