feat: created/beforeCreate

This commit is contained in:
Evan You 2019-09-05 10:07:43 -04:00
parent 54a38ed69f
commit 81a31f79dc
2 changed files with 220 additions and 18 deletions

View File

@ -227,7 +227,145 @@ describe('api: options', () => {
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[] = []
@ -237,8 +375,14 @@ describe('api: options', () => {
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 = {
@ -247,8 +391,14 @@ describe('api: options', () => {
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 = {
@ -258,8 +408,14 @@ describe('api: options', () => {
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}`
@ -267,7 +423,14 @@ describe('api: options', () => {
}
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', () => {

View File

@ -70,8 +70,8 @@ export interface LegacyOptions {
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
@ -100,25 +100,30 @@ export function applyOptions(
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) {
@ -205,8 +210,8 @@ export function applyOptions(
}
// lifecycle options
if (created) {
created.call(ctx)
if (!asMixin) {
callSyncHook('created', options, ctx, globalMixins)
}
if (beforeMount) {
onBeforeMount(beforeMount.bind(ctx))
@ -229,11 +234,45 @@ export function applyOptions(
if (renderTriggered) {
onRenderTracked(renderTriggered.bind(ctx))
}
if (beforeDestroy) {
onBeforeUnmount(beforeDestroy.bind(ctx))
if (beforeUnmount) {
onBeforeUnmount(beforeUnmount.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)
}
if (destroyed) {
onUnmounted(destroyed.bind(ctx))
}
}