Vue 3 Composition API - 如何在 setup() 中指定道具

Vue 3 Composition API - How to specify a prop in setup()

我为 Vue 2 写了一个“加载状态”mixin:

export default {
  props: {
    loading: {
      type: Boolean,
      default: false
    },
  },
  data () {
    return {
      innerLoading: false,
    }
  },
  mounted () {
    this.innerLoading = !!this.loading
  },
  methods: {
    startLoading () {
      this.$emit('update:loading', this.innerLoading = true)
    },
    stopLoading () {
      this.$emit('update:loading', this.innerLoading = false)
    },
  },
  computed: {
    isLoading () {
      return !!this.innerLoading
    },
    isNotLoading () {
      return !this.innerLoading
    },
  },
  watch: {
    loading (loading) {
      this.innerLoading = !!loading
    },
  }
}

我将此 mixin 用于其他组件以保持 loading 状态。例如表单、按钮、表格等

现在,我正在尝试将此 mixin 重写为 Vue 3 的组合 API 样式。理想情况下,我想像这样使用我的 loading 可组合项:

// components/Table.vue

import 'useLoading' from 'src/composables/loading'

export default defineComponent({
  setup () {
    const { startLoading, stopLoading, innerLoading } = useLoading()

    // ...
    
    return { startLoading, stopLoading, innerLoading, ... }
  }
})

我的问题:

// How can I define the loading prop inside the setup() function?
props: {
  loading: {
    type: Boolean,
    default: false
  },
},

当然我可以这样定义我的组件:

import 'useLoading' from 'src/composables/loading'

export default defineComponent({
  props: {
    loading: {
      type: Boolean,
      default: false
    },
  },
  setup () {
    const { startLoading, stopLoading, innerLoading } = useLoading();
  }
})

但是想象一下,我有 20 个组件使用这个 mixin/composable。所以我想只定义 loading 道具 ONCE (就像我在 mixin 中所做的那样)。

有没有办法用合成来做到这一点API?

你也许可以做这样的事情

import {withProps, useLoading} from "src/composables/loading";

export default defineComponent({
  props: {
    ...withProps()
  },
  setup () {
    const { startLoading, stopLoading, innerLoading } = useLoading();
  }
})

其中 withProps 是一个包含您的定义的函数

export const withProps = () => ({
  loading: {
    type: Boolean,
    default: false
  },
})

当然它不需要是一个函数,但在某些情况下它可能会有所帮助并且先发制人地将它变成一个函数可以使 api 保持一致。

在名为 makeLoadingProps 的单独文件中定义一个名为 loadingProps 的对象:

export const loadingProps = {
    loading: {
        type: Boolean,
        default: false
    }
}

然后将其导入到使用 脚本设置 语法定义的组件中:

<script setup lang="ts">

import {defineProps} from 'vue'
import { loadingProps } from 'src/composables/makeLoadingProps';

const props = defineProps({
               ...loadingProps,
                //other props
             })

const { startLoading, stopLoading, innerLoading } = useLoading(props)

</script>