diff --git a/src/core/instance/lifecycle.js b/src/core/instance/lifecycle.js
index 27756af66fc..c9c3b43c1ae 100644
--- a/src/core/instance/lifecycle.js
+++ b/src/core/instance/lifecycle.js
@@ -7,6 +7,7 @@ import { createEmptyVNode } from '../vdom/vnode'
import { observerState } from '../observer/index'
import { updateComponentListeners } from './events'
import { resolveSlots } from './render-helpers/resolve-slots'
+import { pushTarget, popTarget } from '../observer/dep'
import {
warn,
@@ -315,6 +316,8 @@ export function deactivateChildComponent (vm: Component, direct?: boolean) {
}
export function callHook (vm: Component, hook: string) {
+ // #7573 disable dep collection when invoking lifecycle hooks
+ pushTarget()
const handlers = vm.$options[hook]
if (handlers) {
for (let i = 0, j = handlers.length; i < j; i++) {
@@ -328,4 +331,5 @@ export function callHook (vm: Component, hook: string) {
if (vm._hasHookEvent) {
vm.$emit('hook:' + hook)
}
+ popTarget()
}
diff --git a/src/core/instance/state.js b/src/core/instance/state.js
index a42638a13f7..b3888252094 100644
--- a/src/core/instance/state.js
+++ b/src/core/instance/state.js
@@ -1,8 +1,8 @@
/* @flow */
import config from '../config'
-import Dep from '../observer/dep'
import Watcher from '../observer/watcher'
+import Dep, { pushTarget, popTarget } from '../observer/dep'
import { isUpdatingChildComponent } from './lifecycle'
import {
@@ -150,11 +150,15 @@ function initData (vm: Component) {
}
export function getData (data: Function, vm: Component): any {
+ // #7573 disable dep collection when invoking data getters
+ pushTarget()
try {
return data.call(vm, vm)
} catch (e) {
handleError(e, vm, `data()`)
return {}
+ } finally {
+ popTarget()
}
}
diff --git a/src/core/observer/dep.js b/src/core/observer/dep.js
index 5d55e9cd421..abf3b275ce4 100644
--- a/src/core/observer/dep.js
+++ b/src/core/observer/dep.js
@@ -48,7 +48,7 @@ export default class Dep {
Dep.target = null
const targetStack = []
-export function pushTarget (_target: Watcher) {
+export function pushTarget (_target: ?Watcher) {
if (Dep.target) targetStack.push(Dep.target)
Dep.target = _target
}
diff --git a/test/unit/features/options/data.spec.js b/test/unit/features/options/data.spec.js
index cb8a75ad18d..ac431bbd939 100644
--- a/test/unit/features/options/data.spec.js
+++ b/test/unit/features/options/data.spec.js
@@ -93,6 +93,38 @@ describe('Options data', () => {
expect(vm.$refs.test.b).toBe(1)
})
+ it('props should not be reactive', done => {
+ let calls = 0
+ const vm = new Vue({
+ template: ``,
+ data: {
+ msg: 'hello'
+ },
+ beforeUpdate () { calls++ },
+ components: {
+ child: {
+ template: `{{ localMsg }}`,
+ props: ['msg'],
+ data () {
+ return { localMsg: this.msg }
+ },
+ computed: {
+ computedMsg () {
+ return this.msg + ' world'
+ }
+ }
+ }
+ }
+ }).$mount()
+ const child = vm.$children[0]
+ vm.msg = 'hi'
+ waitForUpdate(() => {
+ expect(child.localMsg).toBe('hello')
+ expect(child.computedMsg).toBe('hi world')
+ expect(calls).toBe(1)
+ }).then(done)
+ })
+
it('should have access to methods', () => {
const vm = new Vue({
methods: {