1

这是我的 Vue3 应用程序代码:

<template>
  {{ names_data }}
</template>

<script>
import getData from "./composables/getData"

export default {
  name: "App",
  setup() {
    var filenames = ["test1.json", "test2.json"];
    const { names_data, error, load_data } = getData(
      filenames
    );
    load_data();
    console.log("names", names_data)

    console.log("error", error)

    return { names_data };
  },
};
</script>

导入的可组合函数如下:

import { ref } from "@vue/runtime-core";

const getData = (filenames) => {
  const names_data = ref([])
  const error = ref(null)

  const load_data = async () => {
    try {
      var promises = [];
      for (let i = 0; i < filenames.length; i++) {
        var filename = filenames[i]
        promises.push(
          fetch(`data/${filename}`).then(
            (res) => (res.ok && res.json()) || Promise.reject(res)
          )
        );
      }
      const data = await Promise.all(promises);
      names_data.value = data
    } catch (err) {
      error.value = err.message;
      console.log(error.value);
    }
  };
  return { names_data, error, load_data }
};

export default getData

数据文件包含以下内容:

test1.json

{
  "members": {
    "0": "Alice",
    "1": "Bob",
    "2": "Charlie"
  }
}

test2.json

{
  "members": {
    "0": "David",
    "1": "Elizabeth",
    "2": "Fred"
  }
}

这一切都有效:我可以names_data从屏幕上显示的模板中看到。但是在控制台中names_data显示如下:

RefImpl {_shallow: false, dep: undefined, __v_isRef: true, _rawValue: Array(0), _value: Proxy} dep: Set(1) {ReactiveEffect} __v_isRef: true _rawValue: (2) [{…}, {…} ] _shallow: false _value: 代理 {0: {...}, 1: {...}} value: (...) [[Prototype]]: Object

我希望能够访问其中的值以names_data进行进一步处理,例如将它们放入表中,但是当我console.log(names_data.value)在应用程序中执行此操作时,我会得到一个空数组的代理对象。我认为该names_data对象以某种方式失去了反应性,因为它在load_data()被调用时没有更新。但它显然在模板中是被动的。所以我对这里发生的事情感到困惑。

如何访问 ref 的值以进一步处理它?

4

2 回答 2

1

它按预期工作。如果不使用反应性,这将导致这种流行的竞争条件。使用反应性的要点是值是反应性的,可以通过组合 API 在其他地方组合。

在这种情况下,无需等待load_datasetup正文中完成。它应该在值可用时访问:

const { names_data, error, load_data } = getData(...);
load_data();
watch(names_data, data => {
    console.log(data);
});
于 2021-12-01T14:51:43.240 回答
0

对 Estus Flask 接受的答案的后续回答:

如果我制作names_data字典而不是列表,即通过

...
names_data = ref({})
...
...
    const data = await Promise.all(promises);
    for (let ind=0; ind<data.length; ind++) {
      let filename = filenames[ind]
      names_data.value[filename] = data[ind]
    }
...

然后watch()不再工作。它必须在setup()by中替换,watchEffect()如下所示:

    watchEffect(() => {
      console.log("updated data", names_data.value)
    })
于 2021-12-02T11:28:32.000 回答