typescript 在Svelte中渲染数组的单个元素的正确方法是什么?

3htmauhk  于 2023-05-08  发布在  TypeScript
关注(0)|答案(2)|浏览(131)

我有一个节点数组,在我的例子中,这些节点是包含一些数据的对象,包括id。我只想显示活动节点,它是通过比较节点ID和活动节点ID找到的。我可以成功地使用它:

let active_node_id: string;
active_node_stream.subscribe((value) => (active_node_id = value));

...

{#each nodes as node (node.id)}
  {#if node.id === active_node_id}
    <Node {...node} />
  {/if}
{/each}

然而,这种循环遍历所有节点只显示一个节点的模式似乎是错误的。有没有更好的办法?
我想尝试使用Svelte的React式声明,以便在找到活动节点后停止循环,如下所示:

$: active_node_data = nodes.find(n => n.id === active_node_id)

...

<Node {...active_node_data} />

但这给了我以下错误(我使用的是TypeScript --当我试图重现它时,它似乎是work fine with JavaScript):

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'length')
  at $$self.$$.update

我不知道为什么会发生这个错误,因为active_node_id应该总是匹配节点的ID。当这个错误发生时,我已经记录了节点值和active_node_id,它们确实匹配…
无论如何,这种方法并不比eachif方法好得多。有没有更好的方法保持苗条

enxuqcxy

enxuqcxy1#

我认为被动分配确实是完成这类任务的最好方式。
代码中的问题以及typescript对它不满意的原因是,如果没有找到节点,find可能会返回undefined。
MDN docs -> find:返回数组中 predicate 为true的第一个元素的值,否则返回undefined
所以只要提供一个默认值,以防它是未定义的,像这样的东西就可以做到这一点:

$: active_node_data = nodes.find(n => n.id === active_node_id) ?? {id: "default"}
xiozqbni

xiozqbni2#

我和我的熟人yuanchuan聊了聊这件事。他建议使用Mapif配对,这样感觉更好。
首先,你需要建立一个Map(我在我的节点数据所在的地方做了这个):

export const node_map = build_data_map(nodes);

function build_data_map(nodes: node[]) {
  const map = new Map<string, node>();
  for (const node of nodes) {
    map.set(node.id, node);
  }
  return map;
}

然后,您可以导入该Map并使用它来查找当前活动节点:

let active_node_id: string;
active_node_stream.subscribe((value) => (active_node_id = value));

$: active_node_data = node_map.get(active_node_id);

...

{#if active_node_data}
  <Node {...active_node_data} />
{/if}

因此,使用Svelte的React性是一种方法,但也有更好的方法来做到这一点,如使用Map。
然而,上面提供的方法防止了活动节点发生变化时的转换(在我的例子中,我隐藏了非活动节点)。这是因为上面的方法使用了节点的单个示例,仅切换出数据,而不是真正地将元素移入或移出。因此,我坚持使用原来的方法,使用eachif
旁注:原来Cannot read properties of undefined (reading 'length')错误是来自我的Node组件内部,当某个属性没有被传入某些节点时。它是由这些线引起的:

export let options: answer_obj[] = [];
$: is_choice = options.length !== 0;

我希望选项总是有一个长度(至少是0),有时不是undefined$: is_choice = options?.length !== 0;也抛出了错误,这令人惊讶。但是$: is_choice = options ? options.length !== 0 : false;工作正常。我不明白为什么可选的链接方法不起作用(也许是编译器的问题?))我也不知道为什么这不是each方法的问题。

相关问题