ソースを参照

dx(runtime-core): warn if `this` is used in a `<script setup>` template (#7866)

skirtle 2 年 前
コミット
f01afda159

+ 21 - 0
packages/runtime-core/__tests__/rendererComponent.spec.ts

@@ -354,4 +354,25 @@ describe('renderer: component', () => {
     expect(serializeInner(root)).toBe(`<h1>1</h1>`)
     expect(spy).toHaveBeenCalledTimes(2)
   })
+
+  it('should warn accessing `this` in a <script setup> template', () => {
+    const App = {
+      setup() {
+        return {
+          __isScriptSetup: true
+        }
+      },
+
+      render(this: any) {
+        return this.$attrs.id
+      }
+    }
+
+    const root = nodeOps.createElement('div')
+    render(h(App), root)
+
+    expect(
+      `Property '$attrs' was accessed via 'this'. Avoid using 'this' in templates.`
+    ).toHaveBeenWarned()
+  })
 })

+ 16 - 1
packages/runtime-core/src/componentRenderUtils.ts

@@ -73,9 +73,24 @@ export function renderComponentRoot(
       // withProxy is a proxy with a different `has` trap only for
       // runtime-compiled render functions using `with` block.
       const proxyToUse = withProxy || proxy
+      // 'this' isn't available in production builds with `<script setup>`,
+      // so warn if it's used in dev.
+      const thisProxy =
+        __DEV__ && setupState.__isScriptSetup
+          ? new Proxy(proxyToUse!, {
+              get(target, key, receiver) {
+                warn(
+                  `Property '${String(
+                    key
+                  )}' was accessed via 'this'. Avoid using 'this' in templates.`
+                )
+                return Reflect.get(target, key, receiver)
+              }
+            })
+          : proxyToUse
       result = normalizeVNode(
         render!.call(
-          proxyToUse,
+          thisProxy,
           proxyToUse!,
           renderCache,
           props,