具有深度嵌套对象的精简存储

问题描述 投票:0回答:1

我刚刚从 React(+Redux) 切换到 Svelte,遇到了很多我自己无法解决的问题。主要的一个是绑定深层嵌套的对象

假设我们得到了一些类似于@hgl的数据结构如何将Svelte存储与树状嵌套对象一起使用?。由于@rixo的回答,我了解了如何在单个页面上绑定文件夹和文件组件,当我一次性全部支付并且没有路由时。但是,如果我想为每个文件夹创建专用页面并通过某些

id
访问它(让我们将
name
属性视为
id
,因为它在给定模型中是唯一的),例如:

  • .../文件夹/重要%20work%20stuff
  • .../文件夹/山羊

UPD这是原始问题的REPL

所以我想将不是根,而是嵌套对象绑定到我的页面标签。我的想法:

  • 我可以尝试在我的页面中使用

    $
    制作一个计算道具,例如:

    // ./src/folders/[id]/+page.svelte
    <script lang="ts">
          const urlParams = new URLSearchParams(window.location.search);
          const id = urlParams.get("id");
          import { root } from './stores.js'
          $: thisFolder = $root.find((f) => f.name === id) // root level search
              ?? $root.map((pf) => pf.files?.find((f) => f.name === id)).find((f) => f) // 2nd level search, might continue if needed...
          if (!thisFolder) {
              eror(404, { message: "folder not found", });
          }
      </script>
    
      <div>
          <span>Folder name: </span>
          <input bind:value={thisFolder.name}/> // !!! binding here would not work
      </div>
    

但这行不通,我猜那是因为我们在这里不使用相同的变量,而是使用计算出来的变量。它会对商店中的更改做出反应,但不会将其更改传回商店,如果我错了,请纠正我。 UPD这是REPL

  • 另一种选择是创建派生存储,其中我将传递

    id
    并获取适当的文件夹,但据我所知派生存储不可绑定,而且我不知道如何将
    id
    参数传递给派生店铺。 UPD这是REPL

  • 我的第三个方法是监听输入的变化并更新对象

    on:change
    ,但我想知道这是否可以仅通过绑定来完成(这也是我在React中执行此操作的方式,所以对我来说看起来不是反应性的)

  • 另一种方法是使对象尽可能简单,因此每个 URL 重定向加载仅对应于

    id
    文件夹,但这也就像我在反应中所做的那样,这也不太适合我的应用程序

似乎我一周前在 SO 上看到了我的斗争的相关实现,但此后找不到该主题

UPD添加了一些REPL,看起来第一种方法是正确的,稍后将检查并更新问题

binding svelte
1个回答
0
投票

这就是您创建所需的派生商店的方法。

<script>
    import { derived } from 'svelte/store';
    import { root } from './stores.js'
    import Folder from "./Folder.svelte";
        
    function findFolder(root, id) {
        let target = root.find(child => child.name === id);
        if (target) return target;
        return root.reduce((found, child) => {
            if (found) return found;
            if (child.type === 'folder') {
                return findFolder(child.files, id);
            }
            return null;
        }, null)
    }

    const specificFolder = id => derived(root, $root => findFolder($root, id))
    const goatsFolder = specificFolder(id);
    const id = "Goats"
</script>

<span>Goats folder</span>
<Folder files={$goatsFolder.files} expanded={true} />
<div>{JSON.stringify($goatsFolder)}</div>

<br />
<span>Complete store</span>
<Folder files={$root} expanded={true} />
<div>{JSON.stringify($root)}</div>
© www.soinside.com 2019 - 2024. All rights reserved.