expect(renderToString(h(Root))).toBe(`<!---->1112<!---->`)
})
- test('lifecycle', () => {})
+ test('lifecycle', async () => {
+ const count = ref(0)
+ const root = nodeOps.createElement('div')
+ const calls: string[] = []
+
+ const Root = {
+ beforeCreate() {
+ calls.push('root beforeCreate')
+ },
+ created() {
+ calls.push('root created')
+ },
+ beforeMount() {
+ calls.push('root onBeforeMount')
+ },
+ mounted() {
+ calls.push('root onMounted')
+ },
+ beforeUpdate() {
+ calls.push('root onBeforeUpdate')
+ },
+ updated() {
+ calls.push('root onUpdated')
+ },
+ beforeUnmount() {
+ calls.push('root onBeforeUnmount')
+ },
+ unmounted() {
+ calls.push('root onUnmounted')
+ },
+ render() {
+ return h(Mid, { count: count.value })
+ }
+ }
+
+ const Mid = {
+ beforeCreate() {
+ calls.push('mid beforeCreate')
+ },
+ created() {
+ calls.push('mid created')
+ },
+ beforeMount() {
+ calls.push('mid onBeforeMount')
+ },
+ mounted() {
+ calls.push('mid onMounted')
+ },
+ beforeUpdate() {
+ calls.push('mid onBeforeUpdate')
+ },
+ updated() {
+ calls.push('mid onUpdated')
+ },
+ beforeUnmount() {
+ calls.push('mid onBeforeUnmount')
+ },
+ unmounted() {
+ calls.push('mid onUnmounted')
+ },
+ render() {
+ return h(Child, { count: this.$props.count })
+ }
+ }
+
+ const Child = {
+ beforeCreate() {
+ calls.push('child beforeCreate')
+ },
+ created() {
+ calls.push('child created')
+ },
+ beforeMount() {
+ calls.push('child onBeforeMount')
+ },
+ mounted() {
+ calls.push('child onMounted')
+ },
+ beforeUpdate() {
+ calls.push('child onBeforeUpdate')
+ },
+ updated() {
+ calls.push('child onUpdated')
+ },
+ beforeUnmount() {
+ calls.push('child onBeforeUnmount')
+ },
+ unmounted() {
+ calls.push('child onUnmounted')
+ },
+ render() {
+ return h('div', this.$props.count)
+ }
+ }
+
+ // mount
+ render(h(Root), root)
+ expect(calls).toEqual([
+ 'root beforeCreate',
+ 'root created',
+ 'root onBeforeMount',
+ 'mid beforeCreate',
+ 'mid created',
+ 'mid onBeforeMount',
+ 'child beforeCreate',
+ 'child created',
+ 'child onBeforeMount',
+ 'child onMounted',
+ 'mid onMounted',
+ 'root onMounted'
+ ])
+
+ calls.length = 0
+
+ // update
+ count.value++
+ await nextTick()
+ expect(calls).toEqual([
+ 'root onBeforeUpdate',
+ 'mid onBeforeUpdate',
+ 'child onBeforeUpdate',
+ 'child onUpdated',
+ 'mid onUpdated',
+ 'root onUpdated'
+ ])
+
+ calls.length = 0
+
+ // unmount
+ render(null, root)
+ expect(calls).toEqual([
+ 'root onBeforeUnmount',
+ 'mid onBeforeUnmount',
+ 'child onBeforeUnmount',
+ 'child onUnmounted',
+ 'mid onUnmounted',
+ 'root onUnmounted'
+ ])
+ })
test('mixins', () => {
const calls: string[] = []
a: 1
}
},
+ created() {
+ calls.push('mixinA created')
+ expect(this.a).toBe(1)
+ expect(this.b).toBe(2)
+ expect(this.c).toBe(3)
+ },
mounted() {
- calls.push('mixinA')
+ calls.push('mixinA mounted')
}
}
const mixinB = {
b: 2
}
},
+ created() {
+ calls.push('mixinB created')
+ expect(this.a).toBe(1)
+ expect(this.b).toBe(2)
+ expect(this.c).toBe(3)
+ },
mounted() {
- calls.push('mixinB')
+ calls.push('mixinB mounted')
}
}
const Comp = {
c: 3
}
},
+ created() {
+ calls.push('comp created')
+ expect(this.a).toBe(1)
+ expect(this.b).toBe(2)
+ expect(this.c).toBe(3)
+ },
mounted() {
- calls.push('comp')
+ calls.push('comp mounted')
},
render() {
return `${this.a}${this.b}${this.c}`
}
expect(renderToString(h(Comp))).toBe(`123`)
- expect(calls).toEqual(['mixinA', 'mixinB', 'comp'])
+ expect(calls).toEqual([
+ 'mixinA created',
+ 'mixinB created',
+ 'comp created',
+ 'mixinA mounted',
+ 'mixinB mounted',
+ 'comp mounted'
+ ])
})
test('extends', () => {
updated?(): void
activated?(): void
decativated?(): void
- beforeDestroy?(): void
- destroyed?(): void
+ beforeUnmount?(): void
+ unmounted?(): void
renderTracked?(e: DebuggerEvent): void
renderTriggered?(e: DebuggerEvent): void
errorCaptured?(): boolean | void
components,
directives,
// lifecycle
- // beforeCreate is handled separately
- created,
beforeMount,
mounted,
beforeUpdate,
updated,
// TODO activated
// TODO decativated
- beforeDestroy,
- destroyed,
+ beforeUnmount,
+ unmounted,
renderTracked,
renderTriggered,
errorCaptured
} = options
+ const globalMixins = instance.appContext.mixins
+
+ // beforeCreate
+ if (!asMixin) {
+ callSyncHook('beforeCreate', options, ctx, globalMixins)
+ }
+
// global mixins are applied first, and only if this is a non-mixin call
// so that they are applied once per instance.
if (!asMixin) {
- applyMixins(instance, instance.appContext.mixins)
+ applyMixins(instance, globalMixins)
}
// extending a base component...
if (extendsOptions) {
}
// lifecycle options
- if (created) {
- created.call(ctx)
+ if (!asMixin) {
+ callSyncHook('created', options, ctx, globalMixins)
}
if (beforeMount) {
onBeforeMount(beforeMount.bind(ctx))
if (renderTriggered) {
onRenderTracked(renderTriggered.bind(ctx))
}
- if (beforeDestroy) {
- onBeforeUnmount(beforeDestroy.bind(ctx))
+ if (beforeUnmount) {
+ onBeforeUnmount(beforeUnmount.bind(ctx))
}
- if (destroyed) {
- onUnmounted(destroyed.bind(ctx))
+ if (unmounted) {
+ onUnmounted(unmounted.bind(ctx))
+ }
+}
+
+function callSyncHook(
+ name: 'beforeCreate' | 'created',
+ options: ComponentOptions,
+ ctx: any,
+ globalMixins: ComponentOptions[]
+) {
+ callHookFromMixins(name, globalMixins, ctx)
+ const baseHook = options.extends && options.extends[name]
+ if (baseHook) {
+ baseHook.call(ctx)
+ }
+ const mixins = options.mixins
+ if (mixins) {
+ callHookFromMixins(name, mixins, ctx)
+ }
+ const selfHook = options[name]
+ if (selfHook) {
+ selfHook.call(ctx)
+ }
+}
+
+function callHookFromMixins(
+ name: 'beforeCreate' | 'created',
+ mixins: ComponentOptions[],
+ ctx: any
+) {
+ for (let i = 0; i < mixins.length; i++) {
+ const fn = mixins[i][name]
+ if (fn) {
+ fn.call(ctx)
+ }
}
}