Vue 可组合-如何在不共享状态的情况下使用可组合的多个实例?

Mar*_*der 5 javascript vue.js vuejs3 vue-composition-api

我的 VueJS 应用程序中有一个可组合文件:

// simple example of a composable that fetch some information from API and shows that information 
// in a table in two components at the sime time
export function useDatatable () {
  const table = ref({
    headers: [...],
    items: [],
    someValue: ''
  })

  async function getDocuments () {
    const { data } = await $axios.get('/documents')
    table.value.items = data
  }

  return {
    table,
    getDocuments
  }
}
Run Code Online (Sandbox Code Playgroud)

然后我有多个组件同时使用这个可组合项:

<template>
  <div>
    <document-table /> // composable is used here
    <document-billing-dialog /> // composable is used here too
  </div>
</template>
Run Code Online (Sandbox Code Playgroud)

然后在两个组件(document-tabledocument-billing-dialog)中我都使用这个可组合项,如下所示:

<template>
  <div>
    {{ table.someValue }}
  </div>
  <v-table :items="table.items" />
  <v-btn @click="getDocuments">
    Reload table
  </v-btn>
  // other components
</template>

<script>
  import { useDatatable } from '~/composables/useDatatable'
  // other imports

  export default defineComponent({
    setup () {
      const { table, getDocuments } = useDatatable()

      onMounted(() => { getDocuments() })

      return {
        table,
        getDocuments
      }
    }
  })
</script>
Run Code Online (Sandbox Code Playgroud)

然而,当 1 个组件调用该getDocuments函数时,它会被调用两次,因为它同时在两个组件中使用。

另一个例子是,如果我更改它的值,table.value.someValue = 'something'两个组件都会发生变化。

有没有办法同时拥有可组合项的多个实例而不共享状态?

小智 1

偶然发现了同样的问题。我的解决方案是,分离可组合函数

// simple example of a composable that fetch some information
// from API and shows that information 
// in a table in two components at the sime time

let tables = reactive([])

export default function useDatatable(datatableName) {
  tables[datatableName] = datatable()
  return tables[datatableName]
}

function datatable {
  const table = ref({
    headers: [...],
    items: [],
    someValue: ''
  })

  async function getDocuments() {
    const {
      data
    } = await $axios.get('/documents')
    table.value.items = data
  }

  return {
    table,
    getDocuments
  }
}
Run Code Online (Sandbox Code Playgroud)

使用名称启动可组合项

<script>
  import useDatatable from '~/composables/useDatatable'
  // other imports

  export default defineComponent({
    setup () {
      const { table, getDocuments } = useDatatable('table-1')
    ...
Run Code Online (Sandbox Code Playgroud)