在 Svelte 中将远程数据存储在何处,以便使用 Svelte 和 D3 进行响应式数据可视化(最佳实践)

Rob*_*hrs 2 javascript data-visualization d3.js svelte

免责声明:我对 svelte、D3 和通用 JavaScript 模式都没有太多经验。但我真的很喜欢它,所以我很想学它,并且已经投入了相当长的时间。尽管如此,这感觉像是一个超级基本的问题,让我很恼火。我希望这不会太令人困惑,并且有人可能有想法。

它基本上是关于如何以高效、可重复和“最佳实践”的方式设置一个简单的图表(让它成为一个条形图)。我想我主要关心的是如何传递数据并将其用于不同的任务。例如,我认为将尺度的构造(使用 d3)分离到单独的组件中可能是个好主意。但是,该组件需要访问数据(在最好的情况下,可能还需要访问图表容器的响应宽度)。

然而,位于另一个组件中的条形也需要访问数据才能知道如何绘制矩形。

我对 JavaScript 的一个普遍误解(我想这是正确的词)是我不明白如何异步获取数据(例如使用浏览器fetch或 D3 的 csv方法)。我根本无法获取数据然后将其作为道具传递给另一个组件。因为我要传递的是一个承诺......

所以我有一个非常基本的 REPL,它显示了我脑子里的一些知识:https://svelte.dev/repl/398f4c21b7a9409a9811fd8e38703a36 ?version=3.44.1

看起来像这样。在中App.html,我获取要用于多种目的的数据。但是我无法将其从该组件中“取出”。

<script>
    import Chart from "./Chart.svelte"

    
    const url = "https://api.github.com/search/repositories?q=stars:>100000";
    
    async function getData(){
        let response = await fetch(url)
        let data = await response.json()
        console.log(data)
    }
    
    //async function getDataLocal(){
    //  let data = await d3.csv(<path_to_data>)
    //      return await data
    //  }
    
    
    let data = await getData()
    
</script>

<Chart {data}>Do Something with the data. Make the chart, build the scales, ....</Chart>
Run Code Online (Sandbox Code Playgroud)

所以主要问题是:

  • 是否有任何关于如何学习使用远程数据构建可持续图形的资源,svelte以及一些D3. 我已经看过很多 YouTube 视频,我想我会重看 Matthias Stahl 的一个;)

  • 在这种情况下使用存储来存储数据是个好主意吗

  • 更具体一点:由于数据(可能)是固定的,但尺寸不是:让应用程序知道重新计算比例等的好方法/地方是什么。

Jax*_*axx 8

这里有 3 个不同的问题:

\n
    \n
  • 获取、存储和检索数据(也称为数据源层)
  • \n
  • 操作/转换数据(也称为业务逻辑层)
  • \n
  • 显示数据(又名表示层)
  • \n
\n

我将把最后一部分放在一边,因为它只涉及 D3(如果这是您选择的可视化库),并且网上有大量关于该主题的资源,我将重点关注您问题的核心内容,即如何在 Svelte 中获取数据、将其存储在何处、如何将其传递给组件以及如何操作数据。

\n

1. Svelte中的异步查询

\n

您的第一个询问是关于如何处理异步请求。await您不能在 Svelte 文件部分的根级别使用语句<script>,这意味着以下反应式语句将生成错误:

\n
// will fail\n$: data = await getData(url)\n
Run Code Online (Sandbox Code Playgroud)\n

但是,您可以调用将处理分配的异步函数。当 url 更改并检索新数据时,反应性仍然有效,并且您的组件将重新呈现:

\n
// will work\n$: updateData(url)\n\nasync function updateData(url) {\n  data = await getData(url)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这是一个基于您问题中的 REPL 的工作示例

\n

2. 使用商店

\n

正如您从上面的示例中看到的,您必须将数据传递给您的<Header><Chart>组件才能将其用于以下任一用途:

\n
<Header {data}>GitHub Lookup</Header>\n<Chart {data}/>\n
Run Code Online (Sandbox Code Playgroud)\n

但是,如果您想在应用程序的其他地方使用图表怎么办?如果您有另一个组件想要使用相同的数据怎么办?

\n

显然,您不想一遍又一遍地获取相同的数据(除非请求本身已更改)。您还希望避免将数据作为 prop 传递到应用程序中的任何地方。您将希望仅将数据提供给将使用它的这些组件。

\n

这就是商店派上用场的地方。任何组件都可以订阅商店。可写存储将允许更新其内容,而可读存储(顾名思义)是只读的。

\n

商店不必很复杂。以下是一个非常基本的可写存储:

\n
import { writable } from \'svelte/store\'\n\nexport const githubStore = writable(null) // initialized with a null value\n
Run Code Online (Sandbox Code Playgroud)\n

然后您所要做的就是与您的商店互动。

\n

更新应用程序组件中的商店:

\n
import { githubStore as data } from \'./githubStore.js\' // import the store we defined above under the name \'data\'\n.\n.\n.\nasync function updateData(url) {\n  $data = await getData(url) // using the $ shorthand to access the store (assigning a new value will update the store content)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在组件中使用(即订阅)商店:

\n
import { githubStore as data } from \'./githubStore.js\' // import the store we defined above under the name \'data\'\n.\n.\n.\n// using the $ shorthand to access the store\n{#each $data.items as item (item.id)}\n  <li><a href={item.html_url}>{item.full_name}</a> [{item.stargazers_count}\xe2\xad\x90]</li>\n{/each}\n
Run Code Online (Sandbox Code Playgroud)\n

请阅读此处,了解有关在存储中使用 $ 反应式语法的详细信息

\n

现在您的子组件正在订阅您存储数据的存储,您不再需要将该数据作为 prop 传递:

\n
<Header>GitHub Lookup</Header>\n<Chart />\n
Run Code Online (Sandbox Code Playgroud)\n

这是上面 REPL 的更新版本,使用了 store

\n

3. 进一步考虑

\n

当您想要开始操作或转换已放入存储中的数据时,派生存储会派上用场。当原始存储中的数据更新时,派生存储将根据原始存储的更改自动更新。

\n

您还可以通过添加自己的功能和自定义方法来构建所提供的可读/可写存储。这些是稍微高级的主题,但在涉及数据操作时会派上用场。

\n

最后,D3 将提供自己的数据操作方法,因此您可以决定直接在 Svelte 中处理多少操作,以及委托给 D3 多少操作。我可能会将与可视化相关的所有内容(缩放、缩放等)留在 D3 端,并在 Svelte 端(或者更好,直接在背面)对数据(即业务逻辑)进行实际的预可视化操作-结束,如果你有权访问它!)。

\n