From 3507eb8ea36e87b87c474ebd61d03c4449dcc71d Mon Sep 17 00:00:00 2001
From: kingwl <805037171@163.com>
Date: Mon, 20 Mar 2017 13:44:27 +0800
Subject: [PATCH 1/2] fix provide isn't reactive with a single array - Fix
#5223
---
src/core/instance/inject.js | 3 +-
test/unit/features/options/inject.spec.js | 34 +++++++++++++++++++++++
2 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/src/core/instance/inject.js b/src/core/instance/inject.js
index 0b1a071e3c4..89a98ab49fb 100644
--- a/src/core/instance/inject.js
+++ b/src/core/instance/inject.js
@@ -1,6 +1,7 @@
/* @flow */
import { hasSymbol } from 'core/util/env'
+import { defineReactive } from '../observer/index'
export function initProvide (vm: Component) {
const provide = vm.$options.provide
@@ -29,7 +30,7 @@ export function initInjections (vm: Component) {
let source = vm
while (source) {
if (source._provided && provideKey in source._provided) {
- vm[key] = source._provided[provideKey]
+ defineReactive(vm, key, source._provided[provideKey])
break
}
source = source.$parent
diff --git a/test/unit/features/options/inject.spec.js b/test/unit/features/options/inject.spec.js
index ac67749f43d..86c03717e30 100644
--- a/test/unit/features/options/inject.spec.js
+++ b/test/unit/features/options/inject.spec.js
@@ -162,4 +162,38 @@ describe('Options provide/inject', () => {
expect(vm.$el.textContent).toBe('123')
})
}
+
+ // Github issue #5223
+ it('should work with reactive array', done => {
+ const vm = new Vue({
+ template: `
`,
+ data () {
+ return {
+ foo: []
+ }
+ },
+ provide () {
+ return {
+ foo: this.foo
+ }
+ },
+ components: {
+ child: {
+ inject: ['foo'],
+ template: `{{foo.length}}`
+ }
+ }
+ }).$mount()
+
+ expect(vm.$el.innerHTML).toEqual(`0`)
+ vm.foo.push(vm.foo.length)
+ vm.$nextTick(() => {
+ expect(vm.$el.innerHTML).toEqual(`1`)
+ vm.foo.pop()
+ vm.$nextTick(() => {
+ expect(vm.$el.innerHTML).toEqual(`0`)
+ done()
+ })
+ })
+ })
})
From 4a5733ca915cd3d643202ba8506c74cee8b2b63b Mon Sep 17 00:00:00 2001
From: kingwl <805037171@163.com>
Date: Tue, 21 Mar 2017 12:35:35 +0800
Subject: [PATCH 2/2] add warning when injections has been modified
---
src/core/instance/inject.js | 14 +++++++++++++-
test/unit/features/options/inject.spec.js | 21 +++++++++++++++++++++
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/src/core/instance/inject.js b/src/core/instance/inject.js
index 89a98ab49fb..a2954163140 100644
--- a/src/core/instance/inject.js
+++ b/src/core/instance/inject.js
@@ -1,6 +1,7 @@
/* @flow */
import { hasSymbol } from 'core/util/env'
+import { warn } from '../util/index'
import { defineReactive } from '../observer/index'
export function initProvide (vm: Component) {
@@ -30,7 +31,18 @@ export function initInjections (vm: Component) {
let source = vm
while (source) {
if (source._provided && provideKey in source._provided) {
- defineReactive(vm, key, source._provided[provideKey])
+ if (process.env.NODE_ENV !== 'production') {
+ defineReactive(vm, key, source._provided[provideKey], () => {
+ warn(
+ `Avoid mutating a injections directly since the value will be ` +
+ `overwritten whenever the provided component re-renders. ` +
+ `injections being mutated: "${key}"`,
+ vm
+ )
+ })
+ } else {
+ defineReactive(vm, key, source._provided[provideKey])
+ }
break
}
source = source.$parent
diff --git a/test/unit/features/options/inject.spec.js b/test/unit/features/options/inject.spec.js
index 86c03717e30..bfb5e5bd143 100644
--- a/test/unit/features/options/inject.spec.js
+++ b/test/unit/features/options/inject.spec.js
@@ -196,4 +196,25 @@ describe('Options provide/inject', () => {
})
})
})
+
+ it('should warn when injections has been modified', () => {
+ const key = 'foo'
+ const vm = new Vue({
+ provide: {
+ foo: 1
+ }
+ })
+
+ const child = new Vue({
+ parent: vm,
+ inject: ['foo']
+ })
+
+ expect(child.foo).toBe(1)
+ child.foo = 2
+ expect(
+ `Avoid mutating a injections directly since the value will be ` +
+ `overwritten whenever the provided component re-renders. ` +
+ `injections being mutated: "${key}"`).toHaveBeenWarned()
+ })
})