From 8c54ea663150c63bafa518c19867c65d42105e49 Mon Sep 17 00:00:00 2001 From: Dan Popescu Date: Tue, 8 Aug 2017 10:54:24 +0300 Subject: [PATCH 1/3] feat(inject/provide): Allow defining optional inject dependency with default values Allow to define inject as object with name and default properties. The default is used if no provide is found, and no warning is emitted. #6097 --- src/core/instance/inject.js | 13 ++++++++++--- src/core/util/options.js | 13 +++++++++++-- test/unit/features/options/inject.spec.js | 17 +++++++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/core/instance/inject.js b/src/core/instance/inject.js index 98887c48609..dd56e588855 100644 --- a/src/core/instance/inject.js +++ b/src/core/instance/inject.js @@ -49,7 +49,7 @@ export function resolveInject (inject: any, vm: Component): ?Object { for (let i = 0; i < keys.length; i++) { const key = keys[i] - const provideKey = inject[key] + const provideKey = inject[key].name let source = vm while (source) { if (source._provided && provideKey in source._provided) { @@ -58,8 +58,15 @@ export function resolveInject (inject: any, vm: Component): ?Object { } source = source.$parent } - if (process.env.NODE_ENV !== 'production' && !source) { - warn(`Injection "${key}" not found`, vm) + if (!source) { + if ('default' in inject[key]) { + const provideDefault = inject[key].default + result[key] = typeof provideDefault === 'function' + ? provideDefault.call(vm) + : provideDefault + } else if (process.env.NODE_ENV !== 'production') { + warn(`Injection "${key}" not found`, vm) + } } } return result diff --git a/src/core/util/options.js b/src/core/util/options.js index 70e4d015b4d..37d1942a10c 100644 --- a/src/core/util/options.js +++ b/src/core/util/options.js @@ -270,12 +270,21 @@ function normalizeProps (options: Object) { */ function normalizeInject (options: Object) { const inject = options.inject + const normalized = {} + let val if (Array.isArray(inject)) { - const normalized = options.inject = {} for (let i = 0; i < inject.length; i++) { - normalized[inject[i]] = inject[i] + normalized[inject[i]] = { name: inject[i] } + } + } else if (isPlainObject(inject)) { + for (const key in inject) { + val = inject[key] + normalized[key] = isPlainObject(val) + ? extend({ name: key }, val) + : { name: val } } } + options.inject = normalized } /** diff --git a/test/unit/features/options/inject.spec.js b/test/unit/features/options/inject.spec.js index 86e3ada5736..de3df74843b 100644 --- a/test/unit/features/options/inject.spec.js +++ b/test/unit/features/options/inject.spec.js @@ -370,6 +370,23 @@ describe('Options provide/inject', () => { expect(`Injection "__ob__" not found`).not.toHaveBeenWarned() }) + // Github issue #6097 + it('should not warn when injections cannot be found but have default value', () => { + const vm = new Vue({}) + new Vue({ + parent: vm, + inject: { + foo: { default: 1 }, + bar: { default: false }, + baz: { default: undefined } + }, + created () {} + }) + expect(`Injection "foo" not found`).not.toHaveBeenWarned() + expect(`Injection "bar" not found`).not.toHaveBeenWarned() + expect(`Injection "baz" not found`).not.toHaveBeenWarned() + }) + // Github issue #6008 it('should merge provide from mixins (objects)', () => { const mixinA = { provide: { foo: 'foo' }} From 46beaedff58b9ef0536cf9d4a8a945e65f137951 Mon Sep 17 00:00:00 2001 From: Dan Popescu Date: Wed, 9 Aug 2017 15:04:11 +0300 Subject: [PATCH 2/3] Refactor normalizeInject --- src/core/util/options.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/core/util/options.js b/src/core/util/options.js index 37d1942a10c..11a586961c4 100644 --- a/src/core/util/options.js +++ b/src/core/util/options.js @@ -270,21 +270,19 @@ function normalizeProps (options: Object) { */ function normalizeInject (options: Object) { const inject = options.inject - const normalized = {} - let val + const normalized = options.inject = {} if (Array.isArray(inject)) { for (let i = 0; i < inject.length; i++) { normalized[inject[i]] = { name: inject[i] } } } else if (isPlainObject(inject)) { for (const key in inject) { - val = inject[key] + const val = inject[key] normalized[key] = isPlainObject(val) ? extend({ name: key }, val) : { name: val } } } - options.inject = normalized } /** From 63f43c89a3b158858e70552f5255c39831233ce8 Mon Sep 17 00:00:00 2001 From: Dan Popescu Date: Wed, 9 Aug 2017 15:38:46 +0300 Subject: [PATCH 3/3] Add test for using provided value even if inject has default --- test/unit/features/options/inject.spec.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/unit/features/options/inject.spec.js b/test/unit/features/options/inject.spec.js index de3df74843b..99c78f960c8 100644 --- a/test/unit/features/options/inject.spec.js +++ b/test/unit/features/options/inject.spec.js @@ -387,6 +387,28 @@ describe('Options provide/inject', () => { expect(`Injection "baz" not found`).not.toHaveBeenWarned() }) + it('should use provided value even if inject has default', () => { + const vm = new Vue({ + provide: { + foo: 1, + bar: false, + baz: undefined + } + }) + new Vue({ + parent: vm, + inject: { + foo: { default: 2 }, + bar: { default: 2 }, + baz: { default: 2 } + }, + created () { + injected = [this.foo, this.bar, this.baz] + } + }) + expect(injected).toEqual([1, false, undefined]) + }) + // Github issue #6008 it('should merge provide from mixins (objects)', () => { const mixinA = { provide: { foo: 'foo' }}