瀏覽代碼

fix(runtime-core): component methods should override global properties in DEV (#3074)

HcySunYang 5 年之前
父節點
當前提交
2587f36fe3
共有 2 個文件被更改,包括 31 次插入2 次删除
  1. 20 1
      packages/runtime-core/__tests__/apiOptions.spec.ts
  2. 11 1
      packages/runtime-core/src/componentOptions.ts

+ 20 - 1
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(`<div>2</div>`)
   })
 
+  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

+ 11 - 1
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)
         }