From 2587f36fe311359e2e34f40e8e47d2eebfab7f42 Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Sat, 6 Feb 2021 02:52:40 +0800 Subject: [PATCH] fix(runtime-core): component methods should override global properties in DEV (#3074) --- .../runtime-core/__tests__/apiOptions.spec.ts | 21 ++++++++++++++++++- packages/runtime-core/src/componentOptions.ts | 12 ++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/packages/runtime-core/__tests__/apiOptions.spec.ts b/packages/runtime-core/__tests__/apiOptions.spec.ts index d60842db450..31300410272 100644 --- a/packages/runtime-core/__tests__/apiOptions.spec.ts +++ b/packages/runtime-core/__tests__/apiOptions.spec.ts @@ -8,7 +8,8 @@ import { nextTick, renderToString, ref, - defineComponent + defineComponent, + createApp } from '@vue/runtime-test' describe('api: options', () => { @@ -105,6 +106,24 @@ describe('api: options', () => { expect(serializeInner(root)).toBe(`
2
`) }) + test('component’s own methods have higher priority than global properties', async () => { + const app = createApp({ + methods: { + foo() { + return 'foo' + } + }, + render() { + return this.foo() + } + }) + app.config.globalProperties.foo = () => 'bar' + + const root = nodeOps.createElement('div') + app.mount(root) + expect(serializeInner(root)).toBe(`foo`) + }) + test('watch', async () => { function returnThis(this: any) { return this diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index 2017b98f6af..c836f125493 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -604,7 +604,17 @@ export function applyOptions( for (const key in methods) { const methodHandler = (methods as MethodOptions)[key] if (isFunction(methodHandler)) { - ctx[key] = methodHandler.bind(publicThis) + // In dev mode, we use the `createRenderContext` function to define methods to the proxy target, + // and those are read-only but reconfigurable, so it needs to be redefined here + if (__DEV__) { + Object.defineProperty(ctx, key, { + value: methodHandler.bind(publicThis), + configurable: true, + enumerable: false + }) + } else { + ctx[key] = methodHandler.bind(publicThis) + } if (__DEV__) { checkDuplicateProperties!(OptionTypes.METHODS, key) }