mirror of
https://gitee.com/vuejs/vue.git
synced 2024-12-04 21:17:55 +08:00
ensure updated hook is called after children are updated as well (fix #4599)
This commit is contained in:
parent
299ecfc19f
commit
2ee516dfc8
@ -109,9 +109,8 @@ export function lifecycleMixin (Vue: Class<Component>) {
|
||||
if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {
|
||||
vm.$parent.$el = vm.$el
|
||||
}
|
||||
if (vm._isMounted) {
|
||||
callHook(vm, 'updated')
|
||||
}
|
||||
// updated hook is called by the scheduler to ensure that children are
|
||||
// updated in a parent's updated hook.
|
||||
}
|
||||
|
||||
Vue.prototype._updateFromParent = function (
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
import type Watcher from './watcher'
|
||||
import config from '../config'
|
||||
import { callHook } from '../instance/lifecycle'
|
||||
import {
|
||||
warn,
|
||||
nextTick,
|
||||
@ -32,6 +33,7 @@ function resetSchedulerState () {
|
||||
*/
|
||||
function flushSchedulerQueue () {
|
||||
flushing = true
|
||||
let watcher, id, vm
|
||||
|
||||
// Sort queue before flush.
|
||||
// This ensures that:
|
||||
@ -46,8 +48,8 @@ function flushSchedulerQueue () {
|
||||
// do not cache length because more watchers might be pushed
|
||||
// as we run existing watchers
|
||||
for (index = 0; index < queue.length; index++) {
|
||||
const watcher = queue[index]
|
||||
const id = watcher.id
|
||||
watcher = queue[index]
|
||||
id = watcher.id
|
||||
has[id] = null
|
||||
watcher.run()
|
||||
// in dev build, check and stop circular updates.
|
||||
@ -67,6 +69,16 @@ function flushSchedulerQueue () {
|
||||
}
|
||||
}
|
||||
|
||||
// call updated hooks
|
||||
index = queue.length
|
||||
while (index--) {
|
||||
watcher = queue[index]
|
||||
vm = watcher.vm
|
||||
if (vm._watcher === watcher && vm._isMounted) {
|
||||
callHook(vm, 'updated')
|
||||
}
|
||||
}
|
||||
|
||||
// devtool hook
|
||||
/* istanbul ignore if */
|
||||
if (devtools && config.devtools) {
|
||||
|
@ -156,6 +156,34 @@ describe('Options lifecyce hooks', () => {
|
||||
expect(spy).toHaveBeenCalled()
|
||||
}).then(done)
|
||||
})
|
||||
|
||||
it('should be called after children are updated', done => {
|
||||
const calls = []
|
||||
const vm = new Vue({
|
||||
template: '<div><test ref="child">{{ msg }}</test></div>',
|
||||
data: { msg: 'foo' },
|
||||
components: {
|
||||
test: {
|
||||
template: `<div><slot></slot></div>`,
|
||||
updated () {
|
||||
expect(this.$el.textContent).toBe('bar')
|
||||
calls.push('child')
|
||||
}
|
||||
}
|
||||
},
|
||||
updated () {
|
||||
expect(this.$el.textContent).toBe('bar')
|
||||
calls.push('parent')
|
||||
}
|
||||
}).$mount()
|
||||
|
||||
expect(calls).toEqual([])
|
||||
vm.msg = 'bar'
|
||||
expect(calls).toEqual([])
|
||||
waitForUpdate(() => {
|
||||
expect(calls).toEqual(['child', 'parent'])
|
||||
}).then(done)
|
||||
})
|
||||
})
|
||||
|
||||
describe('beforeDestroy', () => {
|
||||
|
@ -1,6 +1,11 @@
|
||||
import Vue from 'vue'
|
||||
import config from 'core/config'
|
||||
import { queueWatcher } from 'core/observer/scheduler'
|
||||
import { queueWatcher as _queueWatcher } from 'core/observer/scheduler'
|
||||
|
||||
function queueWatcher (watcher) {
|
||||
watcher.vm = {} // mock vm
|
||||
_queueWatcher(watcher)
|
||||
}
|
||||
|
||||
describe('Scheduler', () => {
|
||||
let spy
|
||||
|
Loading…
Reference in New Issue
Block a user