]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): align $parent/$root with the template ref when using expose (...
authorHcySunYang <HcySunYang@outlook.com>
Sun, 7 Feb 2021 13:39:52 +0000 (21:39 +0800)
committerGitHub <noreply@github.com>
Sun, 7 Feb 2021 13:39:52 +0000 (14:39 +0100)
packages/runtime-core/__tests__/apiExpose.spec.ts
packages/runtime-core/src/component.ts
packages/runtime-core/src/componentPublicInstance.ts

index 7695360be59831535d087c7187ef44909f861091..a74edfad543308cacf2869c1cbe90498e959f186 100644 (file)
@@ -141,4 +141,32 @@ describe('api: expose', () => {
     expect(childRef.value).toBeTruthy()
     expect(childRef.value.foo).toBe(1)
   })
+
+  test('with $parent/$root', () => {
+    const Child = defineComponent({
+      render() {
+        expect((this.$parent! as any).foo).toBe(1)
+        expect((this.$parent! as any).bar).toBe(undefined)
+        expect((this.$root! as any).foo).toBe(1)
+        expect((this.$root! as any).bar).toBe(undefined)
+      }
+    })
+
+    const Parent = defineComponent({
+      expose: [],
+      setup(_, { expose }) {
+        expose({
+          foo: 1
+        })
+        return {
+          bar: 2
+        }
+      },
+      render() {
+        return h(Child)
+      }
+    })
+    const root = nodeOps.createElement('div')
+    render(h(Parent), root)
+  })
 })
index 494ae41dc47aa4c386925c575cb80c15e2f28433..406e8e0e4f6bd60aa43a66fb623f70c2fb4a764f 100644 (file)
@@ -510,6 +510,10 @@ export function validateComponentName(name: string, config: AppConfig) {
   }
 }
 
+export function isStatefulComponent(instance: ComponentInternalInstance) {
+  return instance.vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT
+}
+
 export let isInSSRComponentSetup = false
 
 export function setupComponent(
@@ -518,8 +522,8 @@ export function setupComponent(
 ) {
   isInSSRComponentSetup = isSSR
 
-  const { props, children, shapeFlag } = instance.vnode
-  const isStateful = shapeFlag & ShapeFlags.STATEFUL_COMPONENT
+  const { props, children } = instance.vnode
+  const isStateful = isStatefulComponent(instance)
   initProps(instance, props, isStateful, isSSR)
   initSlots(instance, children)
 
index ba7eda893b168bd511a135e7688f38ab2727fe8d..c493fea0b908bf2fa951de4b9250f170ca4ec719 100644 (file)
@@ -1,4 +1,8 @@
-import { ComponentInternalInstance, Data } from './component'
+import {
+  ComponentInternalInstance,
+  Data,
+  isStatefulComponent
+} from './component'
 import { nextTick, queueJob } from './scheduler'
 import { instanceWatch, WatchOptions, WatchStopHandle } from './apiWatch'
 import {
@@ -207,8 +211,11 @@ type PublicPropertiesMap = Record<string, (i: ComponentInternalInstance) => any>
  */
 const getPublicInstance = (
   i: ComponentInternalInstance | null
-): ComponentPublicInstance | null =>
-  i && (i.proxy ? i.proxy : getPublicInstance(i.parent))
+): ComponentPublicInstance | ComponentInternalInstance['exposed'] | null => {
+  if (!i) return null
+  if (isStatefulComponent(i)) return i.exposed ? i.exposed : i.proxy
+  return getPublicInstance(i.parent)
+}
 
 const publicPropertiesMap: PublicPropertiesMap = extend(Object.create(null), {
   $: i => i,
@@ -219,7 +226,7 @@ const publicPropertiesMap: PublicPropertiesMap = extend(Object.create(null), {
   $slots: i => (__DEV__ ? shallowReadonly(i.slots) : i.slots),
   $refs: i => (__DEV__ ? shallowReadonly(i.refs) : i.refs),
   $parent: i => getPublicInstance(i.parent),
-  $root: i => i.root && i.root.proxy,
+  $root: i => getPublicInstance(i.root),
   $emit: i => i.emit,
   $options: i => (__FEATURE_OPTIONS_API__ ? resolveMergedOptions(i) : i.type),
   $forceUpdate: i => () => queueJob(i.update),