Skip to content

Commit 2701fa1

Browse files
Kingwlyyx990803
authored andcommitted
add provide/inject on functional context (#5204)
1 parent beee7d8 commit 2701fa1

File tree

4 files changed

+51
-1
lines changed

4 files changed

+51
-1
lines changed

src/core/instance/inject.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,31 @@ export function initProvide (vm: Component) {
1414
}
1515

1616
export function initInjections (vm: Component) {
17-
const inject: any = vm.$options.inject
17+
const result = resolveInject(vm.$options.inject, vm)
18+
if (result) {
19+
Object.keys(result).forEach(key => {
20+
if (process.env.NODE_ENV !== 'production') {
21+
defineReactive(vm, key, result[key], () => {
22+
warn(
23+
`Avoid mutating an injected value directly since the changes will be ` +
24+
`overwritten whenever the provided component re-renders. ` +
25+
`injection being mutated: "${key}"`,
26+
vm
27+
)
28+
})
29+
} else {
30+
defineReactive(vm, key, result[key])
31+
}
32+
})
33+
}
34+
}
35+
36+
export function resolveInject (inject: any, vm: Component): ?Object {
1837
if (inject) {
1938
// inject is :any because flow is not smart enough to figure out cached
2039
// isArray here
2140
const isArray = Array.isArray(inject)
41+
const result = Object.create(null)
2242
const keys = isArray
2343
? inject
2444
: hasSymbol
@@ -49,5 +69,6 @@ export function initInjections (vm: Component) {
4969
source = source.$parent
5070
}
5171
}
72+
return result
5273
}
5374
}

src/core/vdom/create-component.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import VNode from './vnode'
44
import { createElement } from './create-element'
55
import { resolveConstructorOptions } from '../instance/init'
66
import { resolveSlots } from '../instance/render-helpers/resolve-slots'
7+
import { resolveInject } from '../instance/inject'
78

89
import {
910
warn,
@@ -184,11 +185,15 @@ function createFunctionalComponent (
184185
// gets a unique context - this is necessary for correct named slot check
185186
const _context = Object.create(context)
186187
const h = (a, b, c, d) => createElement(_context, a, b, c, d, true)
188+
189+
// functional injections should not reactive
190+
const injections = resolveInject(Ctor.options.inject, _context)
187191
const vnode = Ctor.options.render.call(null, h, {
188192
props,
189193
data,
190194
parent: context,
191195
children,
196+
injections,
192197
slots: () => resolveSlots(children, context)
193198
})
194199
if (vnode instanceof VNode) {

test/unit/features/options/inject.spec.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,29 @@ describe('Options provide/inject', () => {
144144
expect(child.baz).toBe(3)
145145
})
146146

147+
// Github issue #5194
148+
it('should work with functional', () => {
149+
new Vue({
150+
template: `<child/>`,
151+
provide: {
152+
foo: 1,
153+
bar: false
154+
},
155+
components: {
156+
child: {
157+
functional: true,
158+
inject: ['foo', 'bar'],
159+
render (h, context) {
160+
const { injections } = context
161+
injected = [injections.foo, injections.bar]
162+
}
163+
}
164+
}
165+
}).$mount()
166+
167+
expect(injected).toEqual([1, false])
168+
})
169+
147170
if (typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys)) {
148171
it('with Symbol keys', () => {
149172
const s = Symbol()

types/options.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ export interface RenderContext {
6969
slots(): any;
7070
data: VNodeData;
7171
parent: Vue;
72+
injections: any
7273
}
7374

7475
export interface PropOptions {

0 commit comments

Comments
 (0)