"rust",
"scss",
"text",
- "typescriptreact",
"yml"
]
}
const click = jest.fn()
const childUpdated = jest.fn()
- class Hello extends Component<{}, { count: number }> {
- data() {
- return {
- count: 0
- }
- }
+ class Hello extends Component {
+ count: number = 0
inc() {
this.count++
click()
}
}
- class Child extends Component {
+ class Child extends Component<{ [key: string]: any }> {
updated() {
childUpdated()
}
const click = jest.fn()
const childUpdated = jest.fn()
- class Hello extends Component<{}, { count: number }> {
- data() {
- return {
- count: 0
- }
- }
+ class Hello extends Component {
+ count = 0
inc() {
this.count++
click()
}
render() {
return h(Child, {
- foo: 1,
+ foo: 123,
id: 'test',
class: 'c' + this.count,
style: { color: this.count ? 'red' : 'green' },
}
}
- class Child extends Component<{ foo: number }> {
+ class Child extends Component<{ [key: string]: any; foo: number }> {
static props = {
foo: Number
}
const childUpdated = jest.fn()
const grandChildUpdated = jest.fn()
- class Hello extends Component<{}, { count: number }> {
- data() {
- return {
- count: 0
- }
- }
+ class Hello extends Component {
+ count = 0
inc() {
this.count++
click()
}
}
- class Child extends Component {
+ class Child extends Component<{ [key: string]: any; foo: number }> {
updated() {
childUpdated()
}
}
}
- class GrandChild extends Component<{ foo: number }> {
+ class GrandChild extends Component<{ [key: string]: any; foo: number }> {
static props = {
foo: Number
}
import { ErrorTypes } from './errorHandling'
import { initializeComponentInstance } from './componentUtils'
-export interface ComponentClass extends ComponentClassOptions {
+export interface ComponentClass<P = {}> extends ComponentClassOptions {
options?: ComponentOptions
- new <P = {}, D = {}>(): MergedComponent<P, D>
+ new <P = {}, D = {}>(props?: P): MergedComponent<P, D>
}
export type MergedComponent<P, D> = D & P & ComponentInstance<P, D>
-import { ComponentInstance } from './component'
+import { ComponentInstance, MergedComponent } from './component'
import { Slots } from './vdom'
export type Data = Record<string, any>
-export interface ComponentClassOptions<This = ComponentInstance> {
- props?: ComponentPropsOptions
+export interface ComponentClassOptions<P = {}, This = ComponentInstance> {
+ props?: ComponentPropsOptions<P>
computed?: ComponentComputedOptions<This>
watch?: ComponentWatchOptions<This>
displayName?: string
}
-export interface ComponentOptions<This = ComponentInstance>
- extends ComponentClassOptions<This> {
- data?(): object
+export interface ComponentOptions<P = {}, D = {}, This = MergedComponent<P, D>>
+ extends ComponentClassOptions<P, This> {
+ data?(): D
render?: (this: This, props: Readonly<Data>, slots: Slots, attrs: Data) => any
// TODO other options
readonly [key: string]: any
import {
ComponentClass,
FunctionalComponent,
- Component,
ComponentInstance
} from './component'
import { ComponentOptions } from './componentOptions'
createFragment,
createPortal,
VNodeData,
- BuiltInProps
+ BuiltInProps,
+ Key
} from './vdom'
import { isObservable } from '@vue/observer'
import { warn } from './warning'
export const Fragment = Symbol()
export const Portal = Symbol()
+type RawChildType = VNode | string | number | boolean | null | undefined
+
+export type RawSlots = {
+ [name: string]: () => RawChildrenType
+}
+
+export type RawChildrenType = RawChildType | RawChildType[]
+
export type ElementType =
| string
| FunctionalComponent
| typeof Fragment
| typeof Portal
-type RawChildType = VNode | string | number | boolean | null | undefined
-
-export type RawChildrenType = RawChildType | RawChildType[]
-
interface VNodeFactories {
c: typeof createComponentVNode
e: typeof createElementVNode
p: typeof createPortal
}
-interface createElement {
+// This is used to differentiate the data object from
+// vnodes and arrays
+type Differ = { _isVNode?: never; [Symbol.iterator]?: never }
+
+type OptionsComponent<P> =
+ | (ComponentOptions<P> & { template: string })
+ | (ComponentOptions<P> & { render: Function })
+
+interface createElement extends VNodeFactories {
// element
- (tag: string, data?: VNodeData, children?: any): VNode
+ (
+ tag: string,
+ // TODO support native element properties
+ data?: VNodeData & Differ | null,
+ children?: RawChildrenType | RawSlots
+ ): VNode
+ (tag: string, children?: RawChildrenType): VNode
+ // fragment
+ (
+ tag: typeof Fragment,
+ data?: ({ key?: Key } & Differ) | null,
+ children?: RawChildrenType | RawSlots
+ ): VNode
+ (tag: typeof Fragment, children?: RawChildrenType): VNode
+ // portal
+ (
+ tag: typeof Portal,
+ data?: ({ target: any } & BuiltInProps & Differ) | null,
+ children?: RawChildrenType | RawSlots
+ ): VNode
+ (tag: typeof Portal, children?: RawChildrenType): VNode
+ // object
+ <P>(
+ tag: OptionsComponent<P>,
+ data?: (P & BuiltInProps & Differ) | null,
+ children?: RawChildrenType | RawSlots
+ ): VNode
+ <P>(tag: OptionsComponent<P>, children?: RawChildrenType): VNode
// functional
<P>(
tag: FunctionalComponent<P>,
- data?: P & BuiltInProps | null,
- children?: any
+ data?: (P & BuiltInProps & Differ) | null,
+ children?: RawChildrenType | RawSlots
+ ): VNode
+ <P>(tag: FunctionalComponent<P>, children?: RawChildrenType): VNode
+ // class
+ <P, T extends ComponentInstance<P>>(
+ tag: new () => T & { $props: P },
+ data?: (P & BuiltInProps & Differ) | null,
+ children?: RawChildrenType | RawSlots
): VNode
- // stateful
<P, T extends ComponentInstance<P>>(
tag: new () => T & { $props: P },
- data?: P & BuiltInProps | null,
- children?: any
+ children?: RawChildrenType
): VNode
}
ref
)
}
-}) as createElement & VNodeFactories
+}) as createElement
h.c = createComponentVNode
h.e = createElementVNode
-import { ComponentInstance, ComponentType } from '../component'
+import { ComponentInstance } from '../component'
import { ComponentOptions } from '../componentOptions'
-import { RawVNodeChildren, VNodeData } from '../vdom'
export interface Mixin extends ComponentOptions {}
export function applyMixins(Component: ComponentInstance, mixins: Mixin[]) {}
-
-export function h(tag: ComponentType | string, data: RawVNodeChildren): object
-export function h(
- tag: ComponentType | string,
- data: VNodeData,
- children: RawVNodeChildren
-): object {
- return {}
-}
import { VNodeFlags, ChildrenFlags } from './flags'
import { createComponentClassFromOptions } from './componentUtils'
import { normalizeClass, normalizeStyle, handlersRE, EMPTY_OBJ } from './utils'
-import { ElementType, RawChildrenType } from './h'
+import { RawChildrenType, RawSlots } from './h'
// Vue core is platform agnostic, so we are not using Element for "DOM" nodes.
export interface RenderNode {
slots?: RawSlots | null
}
-export type VNodeData = Record<string, any> & BuiltInProps
+export type VNodeData = {
+ [key: string]: any
+} & BuiltInProps
export type VNodeChildren =
| VNode[] // ELEMENT | PORTAL
[name: string]: Slot
}>
-export type RawSlots = {
- [name: string]: () => RawChildrenType
-}
-
export function createVNode(
flags: VNodeFlags,
tag: string | FunctionalComponent | ComponentClass | RenderNode | null,
export const onRE = /^on/
-// value, checked, selected & muted are always patched as properties
-const domPropsRE = /^domProps|^(?:value|checked|selected|muted)$/
+// value, checked, selected & muted
+// plus anything with upperCase letter in it are always patched as properties
+const domPropsRE = /\W|^(?:value|checked|selected|muted)$/
export function patchData(
el: Element,