From a64ff1957c35270b818aa9cfdfb2acb6e42ce2a9 Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Thu, 25 Oct 2018 01:24:31 +0800 Subject: [PATCH] fix(lifecycle): updated should not be called after component being destroyed (#8381) fix #8076 --- src/core/observer/scheduler.js | 2 +- test/unit/features/options/lifecycle.spec.js | 37 ++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/core/observer/scheduler.js b/src/core/observer/scheduler.js index 176ee2c36f7..d9bf67585da 100644 --- a/src/core/observer/scheduler.js +++ b/src/core/observer/scheduler.js @@ -98,7 +98,7 @@ function callUpdatedHooks (queue) { while (i--) { const watcher = queue[i] const vm = watcher.vm - if (vm._watcher === watcher && vm._isMounted) { + if (vm._watcher === watcher && vm._isMounted && !vm._isDestroyed) { callHook(vm, 'updated') } } diff --git a/test/unit/features/options/lifecycle.spec.js b/test/unit/features/options/lifecycle.spec.js index 3fa152e70c2..ccc9d2106de 100644 --- a/test/unit/features/options/lifecycle.spec.js +++ b/test/unit/features/options/lifecycle.spec.js @@ -199,6 +199,43 @@ describe('Options lifecycle hooks', () => { expect(calls).toEqual(['child', 'parent']) }).then(done) }) + + // #8076 + it('should not be called after destroy', done => { + const updated = jasmine.createSpy('updated') + const destroyed = jasmine.createSpy('destroyed') + + Vue.component('todo', { + template: '
{{todo.done}}
', + props: ['todo'], + destroyed, + updated + }) + + const vm = new Vue({ + template: ` +
+ +
+ `, + data () { + return { + todos: [{ id: 1, done: false }] + } + }, + computed: { + pendingTodos () { + return this.todos.filter(t => !t.done) + } + } + }).$mount() + + vm.todos[0].done = true + waitForUpdate(() => { + expect(destroyed).toHaveBeenCalled() + expect(updated).not.toHaveBeenCalled() + }).then(done) + }) }) describe('beforeDestroy', () => {