前言

在看 expose 函数之前,需知道 composition api 的 setup 函数可获取到的参数`

export default {
	setup(props, context) {
		// Attribute (非响应式对象)
		console.log(context.attrs)

		// 插槽 (非响应式对象)
		console.log(context.slots)

		// 触发事件 (方法)
		console.log(context.emit)
	}
}

官网文档中 context 对象可获取到 slots、attrs、emit 三个非响应式对象。

expose

context 除以上三个对象之外,从源码中可以发现还导出了 expose 函数。

function createSetupContext(
  instance
) {
  const expose = exposed => {
    instance.exposed = proxyRefs(exposed)
  }
  return {
    attrs: instance.attrs,
    slots: instance.slots,
    emit: instance.emit,
    expose
  }
}

追溯调用

const setRef = (
  rawRef: VNodeNormalizedRef,
  oldRawRef: VNodeNormalizedRef | null,
  parentComponent: ComponentInternalInstance,
  parentSuspense: SuspenseBoundary | null,
  vnode: VNode | null
) => {
  //  ...省略部分代码
  let value: ComponentPublicInstance | RendererNode | Record<string, any> | null
  if (!vnode) {
    value = null
  } else {
    if (vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT) {
      // ref value 设置
      value = vnode.component!.exposed || vnode.component!.proxy
    } else {
      value = vnode.el
    }
  }
  //  ...省略部分代码
 }

找到使用 exposed 的函数,是 setRef 时获取的。那么 exposed 的用法一目了然了。

使用案例

// comp-a.vue
{
  name: 'comp-a',
  setup(props, { attrs, slots, emit, expose }) {
    const observed = reactive({
      a: 1
    })
    function setObservedA(value) {
      observed.a = value
    }
    expose({
      setObservedA
    })
    return {
      observed,
    }
  }
}
// comp-b.vue
{
  template: `
    <comp-a ref="compa" />
  `,
  setup() {
    const compa = ref(null)
    onMounted(() => {
      // comp-a 调用 expose 之后, 父组件 ref 拿到的结果为调用 expose 时的参数。而不再是组件实例了
      compa.value.setObservedA(2)
    })
    return {
      compa
    }
  }
}

转载自掘金原文地址

Logo

前往低代码交流专区

更多推荐