mirror of
https://gitee.com/vuejs/vue.git
synced 2024-12-02 12:07:39 +08:00
fix activate hook call timing (fix vue-router#1212)
This commit is contained in:
parent
931aaea8dc
commit
1073035164
@ -9,6 +9,7 @@ declare type VNodeComponentOptions = {
|
||||
}
|
||||
|
||||
declare type MountedComponentVNode = {
|
||||
context: Component;
|
||||
componentOptions: VNodeComponentOptions;
|
||||
componentInstance: Component;
|
||||
parent: VNode;
|
||||
|
@ -270,7 +270,7 @@ export function activateChildComponent (vm: Component, direct?: boolean) {
|
||||
} else if (vm._directInactive) {
|
||||
return
|
||||
}
|
||||
if (vm._inactive || vm._inactive == null) {
|
||||
if (vm._inactive || vm._inactive === null) {
|
||||
vm._inactive = false
|
||||
for (let i = 0; i < vm.$children.length; i++) {
|
||||
activateChildComponent(vm.$children[i])
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
import type Watcher from './watcher'
|
||||
import config from '../config'
|
||||
import { callHook } from '../instance/lifecycle'
|
||||
import { callHook, activateChildComponent } from '../instance/lifecycle'
|
||||
|
||||
import {
|
||||
warn,
|
||||
@ -13,6 +13,7 @@ import {
|
||||
export const MAX_UPDATE_COUNT = 100
|
||||
|
||||
const queue: Array<Watcher> = []
|
||||
const activatedChildren: Array<Component> = []
|
||||
let has: { [key: number]: ?true } = {}
|
||||
let circular: { [key: number]: number } = {}
|
||||
let waiting = false
|
||||
@ -23,7 +24,7 @@ let index = 0
|
||||
* Reset the scheduler's state.
|
||||
*/
|
||||
function resetSchedulerState () {
|
||||
queue.length = 0
|
||||
queue.length = activatedChildren.length = 0
|
||||
has = {}
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
circular = {}
|
||||
@ -36,7 +37,7 @@ function resetSchedulerState () {
|
||||
*/
|
||||
function flushSchedulerQueue () {
|
||||
flushing = true
|
||||
let watcher, id, vm
|
||||
let watcher, id
|
||||
|
||||
// Sort queue before flush.
|
||||
// This ensures that:
|
||||
@ -72,19 +73,15 @@ function flushSchedulerQueue () {
|
||||
}
|
||||
}
|
||||
|
||||
// reset scheduler before updated hook called
|
||||
const oldQueue = queue.slice()
|
||||
// keep copies of post queues before resetting state
|
||||
const activatedQueue = activatedChildren.slice()
|
||||
const updatedQueue = queue.slice()
|
||||
|
||||
resetSchedulerState()
|
||||
|
||||
// call updated hooks
|
||||
index = oldQueue.length
|
||||
while (index--) {
|
||||
watcher = oldQueue[index]
|
||||
vm = watcher.vm
|
||||
if (vm._watcher === watcher && vm._isMounted) {
|
||||
callHook(vm, 'updated')
|
||||
}
|
||||
}
|
||||
// call component updated and activated hooks
|
||||
callActivatedHooks(activatedQueue)
|
||||
callUpdateHooks(updatedQueue)
|
||||
|
||||
// devtool hook
|
||||
/* istanbul ignore if */
|
||||
@ -93,6 +90,35 @@ function flushSchedulerQueue () {
|
||||
}
|
||||
}
|
||||
|
||||
function callUpdateHooks (queue) {
|
||||
let i = queue.length
|
||||
while (i--) {
|
||||
const watcher = queue[i]
|
||||
const vm = watcher.vm
|
||||
if (vm._watcher === watcher && vm._isMounted) {
|
||||
callHook(vm, 'updated')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue a kept-alive component that was activated during patch.
|
||||
* The queue will be processed after the entire tree has been patched.
|
||||
*/
|
||||
export function queueActivatedComponent (vm: Component) {
|
||||
// setting _inactive to false here so that a render function can
|
||||
// rely on checking whether it's in an inactive tree (e.g. router-view)
|
||||
vm._inactive = false
|
||||
activatedChildren.push(vm)
|
||||
}
|
||||
|
||||
function callActivatedHooks (queue) {
|
||||
for (let i = 0; i < queue.length; i++) {
|
||||
queue[i]._inactive = true
|
||||
activateChildComponent(queue[i], true /* true */)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Push a watcher into the watcher queue.
|
||||
* Jobs with duplicate IDs will be skipped unless it's
|
||||
|
@ -1,7 +1,8 @@
|
||||
/* @flow */
|
||||
|
||||
import VNode from './vnode'
|
||||
import { resolveConstructorOptions } from '../instance/init'
|
||||
import { resolveConstructorOptions } from 'core/instance/init'
|
||||
import { queueActivatedComponent } from 'core/observer/scheduler'
|
||||
import { createFunctionalComponent } from './create-functional-component'
|
||||
|
||||
import {
|
||||
@ -61,21 +62,32 @@ const componentVNodeHooks = {
|
||||
},
|
||||
|
||||
insert (vnode: MountedComponentVNode) {
|
||||
if (!vnode.componentInstance._isMounted) {
|
||||
vnode.componentInstance._isMounted = true
|
||||
callHook(vnode.componentInstance, 'mounted')
|
||||
const { context, componentInstance } = vnode
|
||||
if (!componentInstance._isMounted) {
|
||||
componentInstance._isMounted = true
|
||||
callHook(componentInstance, 'mounted')
|
||||
}
|
||||
if (vnode.data.keepAlive) {
|
||||
activateChildComponent(vnode.componentInstance, true /* direct */)
|
||||
if (context._isMounted) {
|
||||
// vue-router#1212
|
||||
// During updates, a kept-alive component's child components may
|
||||
// change, so directly walking the tree here may call activated hooks
|
||||
// on incorrect children. Instead we push them into a queue which will
|
||||
// be processed after the whole patch process ended.
|
||||
queueActivatedComponent(componentInstance)
|
||||
} else {
|
||||
activateChildComponent(componentInstance, true /* direct */)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
destroy (vnode: MountedComponentVNode) {
|
||||
if (!vnode.componentInstance._isDestroyed) {
|
||||
const { componentInstance } = vnode
|
||||
if (!componentInstance._isDestroyed) {
|
||||
if (!vnode.data.keepAlive) {
|
||||
vnode.componentInstance.$destroy()
|
||||
componentInstance.$destroy()
|
||||
} else {
|
||||
deactivateChildComponent(vnode.componentInstance, true /* direct */)
|
||||
deactivateChildComponent(componentInstance, true /* direct */)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user