1

我一直在尝试使用 VueJS 中的新组合 API,但不确定如何解决问题。我正在寻找有关如何正确实施解决方案的一些建议。当一切都基于 vuex 时,这不是问题,因为您可以毫无问题地将操作分派到另一个模块。但是,我正在努力寻找组合实现的解决方案。

问题:

  1. 组件调用CompositionA的函数。
  2. CompositionA触发登录功能。
  3. CompositionA的登录成功/失败响应中,我想调用一个CompositionB函数。(CompositionB 包含用于显示在整个站点中使用的小吃店的数据和逻辑)

问题是有必要在每个组件中注入小吃栏依赖项,而不是从CompositionA实例化/安装它。目前的解决方案是达到这个效果:

Component.vue:

// template calls login(credentials) method
import { useCompositionA } from '@/compositions/compositionA'
import { useCompositionB } from '@/compositions/compositionB'
export default {
  name: 'Component',
  setup(props, context) {
    const { login } = useCompositionA(props, context, useCompositionB(props, context))
    return {
      login
    }
  },
}

compositionA.js:

export const useAuth = (props, context, snack) => {
  const login = async (credentials) => {
    try {
      return await loginWithEmailPassword(credentials)
      snack.show({text: 'Welcome back!'})
    } catch (err) {
      snack.show({text: 'Failed to login'})
    }
  }
  return { login }
}


compositionB.js:

export const useSnack = (props, context) => {
  const snack = reactive({
    color: 'success',
    text: null,
    timeout: 6000,
    visible: true,
  })

  const snackRefs = toRefs(snack)

  const show = ({ text, timeout, color }) => {
    snackRefs.text.value = text
    snackRefs.timeout.value = timeout || 6000
    snackRefs.color.value = color || 'success'
    snackRefs.visible.value = true
  }
  return { 
    ...snackRefs,
    show
  }
}

如果存在类似下面的东西会很好,但我发现如果从CompositionA使用属性,则该属性在CompositionB中不是反应性的(方法被调用但小吃栏不显示)。我的理解是 Vue 没有将CompositionB注入到Component中,所以我只是在 CompositionA 中运行CompositionB另一个实例。我做错了什么?这里的正确解决方案是什么?

compositionA.js (not working):

import { useCompositionB } from '@/compositions/compositionB'
export const useAuth = (props, context) => {
  const login = async (credentials) => {
    const { show } = useCompositionB()
    try {
      return await loginWithEmailPassword(credentials)
      show({text: 'Welcome back!'})
    } catch (err) {
      show({text: 'Failed to login'})
    }
  }
  return { login }
}

提前致谢,

4

1 回答 1

2

正如预期的那样,这是由于Component引用了它自己的CompositionB*本地副本。解决方案实际上是根据以下方式将您的作品状态带入全局范围:

https://vueschool.io/articles/vuejs-tutorials/state-management-with-composition-api/

像这样的东西:

compositionB.js:

const snack = reactive({
  color: 'success',
  text: null,
  timeout: 6000,
  visible: true,
})
export const useSnack = (props, context) => {

  const snackRefs = toRefs(snack)

  const show = ({ text, timeout, color }) => {
    snackRefs.text.value = text
    snackRefs.timeout.value = timeout || 6000
    snackRefs.color.value = color || 'success'
    snackRefs.visible.value = true
  }
  return { 
    ...snackRefs,
    show
  }
}

奇迹般有效。

我最初发现的唯一警告是组合 API 错误:

Uncaught Error: [vue-composition-api] must call Vue.use(plugin) before using any function.

这很容易通过按照这里的解决方案在 main.js 中安装 composition-api 的第一件事来解决:

未捕获的错误:[vue-composition-api] 必须在使用任何函数之前调用 Vue.use(plugin)

我认为这不会是 vue3 出来的问题。希望这可以帮助某人。

于 2020-05-30T18:10:32.247 回答