【问题标题】:Vue 3 Composition API - How to specify a prop in setup()Vue 3 Composition API - 如何在 setup() 中指定道具
【发布时间】:2021-03-12 16:59:24
【问题描述】:

我为 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 来做到这一点?

【问题讨论】:

  • @mspiderv props 不能在 setup() 中声明。由于setup() 本身接收props 值作为其第二个参数,因此必须在调用setup() 之前声明props。目前,声明 props 的唯一方法是使用 Options API。
  • 你最终是如何实现这个的?您是如何在可组合内的观察者中访问 loading 属性的?
  • @Donkarnash 我通过创建两个函数来实现它:useLoadingwithLoadinguseLoading 包含整个逻辑,withLoading 返回的 props 与 @Daniel 所说的 (stackoverflow.com/a/66604160/2987610) 完全相同。我没有在我的新实现中使用 watcher,但在我看来你不是在问别的问题。
  • 感谢您的回复。在useLoading 中,您拥有所有逻辑,如何访问使用useLoading 可组合组件的props?我可以理解,在消费组件中,您包含...withLoading() 来声明道具loading,但是您如何访问useLoading 中的道具?
  • @Donkarnash 像这样:export function useLoading (props, ctx) { props.loading; } 当然,你需要将propsctx 传递给useLoading,像这样:setup (props, ctx) { const { ... } = useLoading(props, ctx); return [ ... ] } 另一种语法是这样的:setup(props, ctx) { return [ ...useLoading(props, ctx) ] } 或这个:setup: useLoading

标签: vue.js vuejs3 vue-composition-api vue-mixin


【解决方案1】:

你也许可以做这样的事情

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 保持一致。

【讨论】:

    【解决方案2】:

    您可以使用一个名为 loadable 的 mixin,它具有 loading 属性:

    export default{
     props: {
      loading: {
        type: Boolean,
        default: false
      },
    },
    }
    

    然后将其导入到您的组件中并将其添加到mixins 选项中:

    import useLoading from 'src/composables/loading'
    import loadable from 'src/mixins/loadable'
    
    export default defineComponent({
     mixins:[loadable],// you could also add other mixins that contain other props like colorable
      setup (props) {
        // here you could use props.loading
        const { startLoading, stopLoading, innerLoading } = useLoading();
      }
    

    注意:mixin 可以定义其他选项,例如 datacomputed,如果您只想使用组合 API,则 mixin 应该只定义 props 以使您的代码保持一致。

    如果您不想使用 mixins,可以查看 this example

    【讨论】:

      猜你喜欢
      • 2020-03-26
      • 1970-01-01
      • 2020-02-13
      • 2021-08-15
      • 2021-09-26
      • 2020-06-16
      • 2020-05-30
      • 2022-06-29
      • 1970-01-01
      相关资源
      最近更新 更多