如何访问 `setup` 的内部状态而不通过 `data` 暴露它?

How to access `setup`'s inner state without exposing it via `data`?

此问题特定于 setup 返回渲染函数。

例如,我有一个组件 Foo:

// Foo.tsx
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {
    //  how to access `number` outside the `Foo` Component?
    const number = ref(0)

    return () => <div>{number.value}</div>
  },
})

我们是否必须使用 data 来暴露 number?例如:

// Foo.tsx
import { defineComponent, getCurrentInstance } from 'vue'

export default defineComponent({
  data() {
    return {
      //  expose `number` to the outside
      number: 0,
    }
  },
  setup() {
    return () => <div>{getCurrentInstance()?.data.number}</div>
  },
})

// FooContainer.tsx
import Foo from '@/views/Foo'
import { defineComponent, onMounted, ref } from 'vue'

export default defineComponent({
  setup() {
    const foo = ref<InstanceType<typeof Foo>>()
    //                           use `Foo`'s `number` in `FooContainer`
    onMounted(() => console.log(foo.value?.number))

    return () => <Foo ref={foo} />
  },
})

那么,有没有其他方法可以访问 Foosetup 的内部状态 number 而无需通过 data 公开它?

您可以使用设置中提供的 expose 方法将您的数据公开给其他组件,

// Foo.tsx
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup(props, { expose }) {
    //  how to access `number` outside the `Foo` Component?
    const number = ref(0)

    expose({
        number
    })

    return () => <div>{number.value}</div>
  },
})

您可以定义一个名为 useLoader:

的可组合函数

useLoader.ts:

import { ref } from 'vue'

const loading = ref(false)

export default function useLoader() {
  return {
    loading,
  }
}

然后在 Foo.tsx 中使用它,例如:

import { defineComponent, getCurrentInstance } from 'vue'
import useLoader from './userLoader'

export default defineComponent({
  setup() {
    const { loading } = useLoader()

    return () => <div>{loading.value && <div> Loading ... </div>}</div>
  },
})

FooContainer.tsx

import Foo from '@/views/Foo'
import { defineComponent, onMounted, ref } from 'vue'
import useLoader from './userLoader'

export default defineComponent({
  setup() {
    const { loading } = useLoader()

    onMounted(() => console.log(loading.value))

    return () => <Foo />
  },
})