Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement inheritAttrs #153

Merged
merged 34 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
bb26087
feat(vapor): implement inheritAttrs
Doctor-wu Mar 17, 2024
7e1f592
feat(runtime-vapor): apply inheritAttrs to instance
Doctor-wu Mar 17, 2024
9d8c1e5
feat(runtime-vapor): extract apiSetup & init setup ctx
Doctor-wu Mar 17, 2024
20aa749
feat(runtime-vapor): add setup ctx type
Doctor-wu Mar 17, 2024
e4bc5ab
Revert "feat(runtime-vapor): add setup ctx type"
Doctor-wu Mar 17, 2024
2f8b9af
Revert "feat(runtime-vapor): extract apiSetup & init setup ctx"
Doctor-wu Mar 17, 2024
757aa74
feat(runtime-vapor): impl fallthrough attrs
Doctor-wu Mar 17, 2024
2db5e19
test(runtime-vapor): tweak props test case
Doctor-wu Mar 17, 2024
8498ba6
feat(runtime-vapor): update attrs when props update
Doctor-wu Mar 17, 2024
1742efe
feat(runtime-vapor): remove unecessary property & use proper way to s…
Doctor-wu Mar 18, 2024
e082299
feat(runtime-vapor, compiler-vapor): add withAttr in singleRoot Compo…
Doctor-wu Mar 18, 2024
5cab771
feat(runtime-vapor, compiler-vapor): resolve nest component attrs
Doctor-wu Mar 18, 2024
1482a20
feat(compiler-vapor): remove unecessary clone props
Doctor-wu Mar 18, 2024
b3b6622
feat(runtime-vapor): clean code
Doctor-wu Mar 18, 2024
791f533
chore(runtime-vapor): make lint happy
Doctor-wu Mar 18, 2024
f7d4c13
feat(runtime-vapor, compiler-vapor): make inheritAttrs reactive
Doctor-wu Mar 18, 2024
bdc1ee4
chore(runtime-vapor): remove unecessary code
Doctor-wu Mar 18, 2024
35499bd
feat(runtime-vapor): should not withAttrs when component set inheritA…
Doctor-wu Mar 18, 2024
a474ac4
feat(runtim-vapor, compiler-vapor): simplify implement
Doctor-wu Mar 18, 2024
24488bc
Merge branch 'main' into feature-inherit-attrs
Doctor-wu Mar 18, 2024
6044bf7
test(compiler-vapor): add generator component test case & snapshot
Doctor-wu Mar 18, 2024
8afe97d
Merge branch 'main' into feature-inherit-attrs
Doctor-wu Mar 18, 2024
c30a618
feat(runtime-vapor): simplify implement
Doctor-wu Mar 18, 2024
c085cda
feat(runtime-vapor): simplify implement
Doctor-wu Mar 18, 2024
0ea395c
refactor: optimize bundle size
sxzz Mar 18, 2024
b5879d3
refactor: check if component
sxzz Mar 18, 2024
322f0ba
refactor: remove type casting
sxzz Mar 18, 2024
34c1937
feat(compiler-vapor): optimize single root implemention
Doctor-wu Mar 18, 2024
56ff7c4
fix: type error
sxzz Mar 18, 2024
47754b7
feat(compiler-vapor): perf bundle size
Doctor-wu Mar 18, 2024
5270734
chore(compiler-vapor, runtime-vapor): bundle size & make lint happy
Doctor-wu Mar 18, 2024
c068506
refactor: simplify
sxzz Mar 18, 2024
61b572c
chore(compiler-vapor): remove unecessary import
Doctor-wu Mar 18, 2024
47f8b9a
test: undo
sxzz Mar 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions packages/runtime-vapor/__tests__/componentAttrs.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {
createComponent,
defineComponent,
getCurrentInstance,
nextTick,
ref,
setText,
template,
toRefs,
watch,
watchEffect,
} from '../src'
import { setCurrentInstance } from '../src/component'
import { makeRender } from './_utils'

const define = makeRender<any>()

describe('attribute fallthrough', () => {
it('should allow attrs to fallthrough', async () => {
const t0 = template('<div>')
const { component: Child } = define({
props: ['foo'],
render() {
const instance = getCurrentInstance()!
const n0 = t0()
watchEffect(() => setText(n0, instance.props.foo))
return n0
},
})

const foo = ref(1)
const id = ref('a')
const { instance, host } = define({
setup() {
return { foo, id }
},
render(_ctx: Record<string, any>) {
return createComponent(Child, {
foo: () => _ctx.foo,
id: () => _ctx.id,
})
},
}).render()
const reset = setCurrentInstance(instance)
expect(host.innerHTML).toBe('<div id="a">1</div>')

foo.value++
await nextTick()
expect(host.innerHTML).toBe('<div id="a">2</div>')

id.value = 'b'
await nextTick()
expect(host.innerHTML).toBe('<div id="b">2</div>')
reset()
})
})
5 changes: 2 additions & 3 deletions packages/runtime-vapor/__tests__/componentProps.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ describe('component: props', () => {
test('optimized props updates', async () => {
const t0 = template('<div>')
const { component: Child } = define({
inheritAttrs: false,
props: ['foo'],
render() {
const instance = getCurrentInstance()!
Expand All @@ -245,17 +246,14 @@ describe('component: props', () => {
},
}).render()
const reset = setCurrentInstance(instance)
// expect(host.innerHTML).toBe('<div id="a">1</div>') // TODO: Fallthrough Attributes
expect(host.innerHTML).toBe('<div>1</div>')

foo.value++
await nextTick()
// expect(host.innerHTML).toBe('<div id="a">2</div>') // TODO: Fallthrough Attributes
expect(host.innerHTML).toBe('<div>2</div>')

id.value = 'b'
await nextTick()
// expect(host.innerHTML).toBe('<div id="b">2</div>') // TODO: Fallthrough Attributes
reset()
})

Expand Down Expand Up @@ -441,6 +439,7 @@ describe('component: props', () => {
// #5016
test('handling attr with undefined value', () => {
const { render, host } = define({
inheritAttrs: false,
render() {
const instance = getCurrentInstance()!
const t0 = template('<div></div>')
Expand Down
17 changes: 14 additions & 3 deletions packages/runtime-vapor/src/apiRender.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { isArray, isFunction, isObject } from '@vue/shared'
import { type ComponentInternalInstance, setCurrentInstance } from './component'
import { insert, querySelector, remove } from './dom/element'
import { flushPostFlushCbs, queuePostRenderEffect } from './scheduler'
import { proxyRefs } from '@vue/reactivity'
import {
createVaporPreScheduler,
flushPostFlushCbs,
queuePostRenderEffect,
} from './scheduler'
import { baseWatch, proxyRefs } from '@vue/reactivity'
import { invokeLifecycle } from './componentLifecycle'
import { VaporLifecycleHooks } from './apiLifecycle'
import { fallThroughAttrs } from './componentAttrs'

export const fragmentKey = Symbol(__DEV__ ? `fragmentKey` : ``)

Expand Down Expand Up @@ -47,7 +52,13 @@ export function setupComponent(instance: ComponentInternalInstance): void {
// TODO: warn no template
block = []
}
return (instance.block = block)
instance.block = block
if (instance.inheritAttrs !== false) {
baseWatch(() => fallThroughAttrs(instance), undefined, {
scheduler: createVaporPreScheduler(instance),
})
}
return block
})
reset()
}
Expand Down
9 changes: 9 additions & 0 deletions packages/runtime-vapor/src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export type FunctionalComponent = SetupFn & Omit<ObjectComponent, 'setup'>

export interface ObjectComponent {
props?: ComponentPropsOptions
inheritAttrs?: boolean
emits?: EmitsOptions
setup?: SetupFn
render?(ctx: any): Block
Expand Down Expand Up @@ -60,6 +61,11 @@ export interface ComponentInternalInstance {
emitted: Record<string, boolean> | null
attrs: Data
refs: Data
/**
* resolved inheritAttrs options
* @internal
*/
inheritAttrs?: boolean
Doctor-wu marked this conversation as resolved.
Show resolved Hide resolved

// lifecycle
isMounted: boolean
Expand Down Expand Up @@ -224,6 +230,9 @@ export function createComponentInstance(
*/
// [VaporLifecycleHooks.SERVER_PREFETCH]: null,
}
if (component.inheritAttrs != null) {
instance.inheritAttrs = component.inheritAttrs
}
initProps(instance, rawProps, !isFunction(component))
instance.emit = emit.bind(null, instance)

Expand Down
20 changes: 19 additions & 1 deletion packages/runtime-vapor/src/componentAttrs.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { camelize, isFunction } from '@vue/shared'
import { camelize, isArray, isFunction } from '@vue/shared'
import type { ComponentInternalInstance } from './component'
import { isEmitListener } from './componentEmits'
import type { Block } from './apiRender'

export function patchAttrs(instance: ComponentInternalInstance) {
const attrs = instance.attrs
Expand Down Expand Up @@ -42,3 +43,20 @@ export function patchAttrs(instance: ComponentInternalInstance) {
}
}
}

export function fallThroughAttrs(instance: ComponentInternalInstance) {
const attrs = instance.attrs
const block = getFallThroughNode(instance.block!)
if (!block) return
for (const key in attrs) {
if (block instanceof Element) {
block.setAttribute(key, String(attrs[key]))
}
}
}

function getFallThroughNode(block: Block) {
if (block instanceof Node) return block
if (isArray(block) && block.length === 1) return getFallThroughNode(block[0])
return null
}