From 127949dedba80393e2722d137bc7613ea5cd951a Mon Sep 17 00:00:00 2001 From: kingwl <805037171@163.com> Date: Thu, 16 Mar 2017 13:47:54 +0800 Subject: [PATCH] add provide/inject on functional context --- src/core/instance/inject.js | 11 +++++++++-- src/core/vdom/create-component.js | 3 +++ test/unit/features/options/inject.spec.js | 23 +++++++++++++++++++++++ types/options.d.ts | 1 + 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/core/instance/inject.js b/src/core/instance/inject.js index 0b1a071e3c4..4d130e3ed90 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 { extend } from 'shared/util' export function initProvide (vm: Component) { const provide = vm.$options.provide @@ -12,11 +13,16 @@ export function initProvide (vm: Component) { } export function initInjections (vm: Component) { - const inject: any = vm.$options.inject + const result = resolveInject(vm.$options.inject, vm) + extend(vm, result) +} + +export function resolveInject (inject: any, vm: Component): ?Object { if (inject) { // inject is :any because flow is not smart enough to figure out cached // isArray here const isArray = Array.isArray(inject) + const result = Object.create(null) const keys = isArray ? inject : hasSymbol @@ -29,11 +35,12 @@ export function initInjections (vm: Component) { let source = vm while (source) { if (source._provided && provideKey in source._provided) { - vm[key] = source._provided[provideKey] + result[key] = source._provided[provideKey] break } source = source.$parent } } + return result } } diff --git a/src/core/vdom/create-component.js b/src/core/vdom/create-component.js index dcae1062cde..b26a3f6b100 100644 --- a/src/core/vdom/create-component.js +++ b/src/core/vdom/create-component.js @@ -4,6 +4,7 @@ import VNode from './vnode' import { createElement } from './create-element' import { resolveConstructorOptions } from '../instance/init' import { resolveSlots } from '../instance/render-helpers/resolve-slots' +import { resolveInject } from '../instance/inject' import { warn, @@ -183,11 +184,13 @@ function createFunctionalComponent ( // gets a unique context - this is necessary for correct named slot check const _context = Object.create(context) const h = (a, b, c, d) => createElement(_context, a, b, c, d, true) + const injections = resolveInject(Ctor.options.inject, _context) const vnode = Ctor.options.render.call(null, h, { props, data, parent: context, children, + injections, slots: () => resolveSlots(children, context) }) if (vnode instanceof VNode) { diff --git a/test/unit/features/options/inject.spec.js b/test/unit/features/options/inject.spec.js index ac67749f43d..b0890003955 100644 --- a/test/unit/features/options/inject.spec.js +++ b/test/unit/features/options/inject.spec.js @@ -144,6 +144,29 @@ describe('Options provide/inject', () => { expect(child.baz).toBe(3) }) + // Github issue #5194 + it('should work with functional', () => { + new Vue({ + template: ``, + provide: { + foo: 1, + bar: false + }, + components: { + child: { + functional: true, + inject: ['foo', 'bar'], + render (h, context) { + const { injections } = context + injected = [injections.foo, injections.bar] + } + } + } + }).$mount() + + expect(injected).toEqual([1, false]) + }) + if (typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys)) { it('with Symbol keys', () => { const s = Symbol() diff --git a/types/options.d.ts b/types/options.d.ts index de1b20d995d..88dccec3739 100644 --- a/types/options.d.ts +++ b/types/options.d.ts @@ -69,6 +69,7 @@ export interface RenderContext { slots(): any; data: VNodeData; parent: Vue; + injections: any } export interface PropOptions {