嵌套组件在 Svelte/Sapper 中无法正确呈现
Nested component does not render properly in Svelte/Sapper
我在 slug 中有三个文件。我使用 slug 参数作为目录名称。
我遇到的问题是除了 taglist 中的每个循环之外的所有问题。由于某种原因,它没有收到道具 tagList
。任何帮助将不胜感激。
index.svelte
<script context="module">
export function preload({ params }, { user }) {
let [id, slug] = [params.id, params.slug];
return { id, slug };
}
</script>
<script>
import Editor from "../../../_components/Editor.svelte";
import Topics from "./Topics.svelte";
import { stores } from "@sapper/app";
export let id;
export let slug;
const { session } = stores();
</script>
<svelte:head>
<title />
</svelte:head>
<div class="editor-page">
<div class="container page">
<div class="row">
<div class="col-md-8 offset-md-2 col-xs-12">
<Topics {id} {slug} />
{#if $session.user}
<Editor />
{/if}
</div>
</div>
</div>
</div>
Topics.svelte
<script>
import { onMount } from "svelte";
import * as api from "api.js";
import "bytemd/dist/index.min.css";
import TagList from "../../../_components/_TagList.svelte";
export let id;
export let slug;
let topics = [];
let title = "";
let tagList = [];
let value = "";
let Viewer = null;
onMount(async () => {
const bytemd = await import("bytemd");
Viewer = bytemd.Viewer;
const response = await api.get(
`t/${id}/${slug}`,
localStorage.getItem("jwt")
);
console.log(response);
if (response.topic) {
topics = response.topic;
title = response.title;
value = topics[0].description;
for(let i= 0; i < response.tags.length; i++) {
tagList.push(response.tags[i]);
}
}
});
</script>
<div>
<h3>{title}</h3>
<hr/>
<svelte:component this={Viewer} {value} />
<TagList {tagList} />
</div>
_TagList.svelte
<script>
export let tagList;
console.log(tagList);
</script>
<ul>
{#each tagList as tag}
<p>hello</p>
<li>{tag.name}</li>
{/each}
</ul>
在 Svelte 中,更新仅通过分配触发。
在您的情况下,这意味着当呈现组件时,它将呈现一个空的标签列表 (tagList = []
)。
现在在 onMount
中您执行 taglist.push
,但如前所述,这不会触发更新(请记住此函数在 after 后调用该组件已安装)因为它不是一个分配。
有四种方法可以解决您的问题:
- 在执行 for 循环后
tagList = tagList
,这是一个赋值,将触发更新。
- 不要执行 for 循环,而是使用映射
tagList = response.tags.map(tag => tag)
- 不是执行 for 循环,而是将标签分散到标签列表中
tagList = [...response.tags]
- 考虑到你无论如何都不对标签做任何事情,而且 tagList 是空的而且你似乎没有任何其他更新方式,直接将标签分配给它
tagList = response.tags
当然你的代码可能会被简化,如果你在将每个标签添加到列表之前实际对它做一些事情,情况 3 和 4 不是好的选择,对于那种情况我会使用 map
选项
我在 slug 中有三个文件。我使用 slug 参数作为目录名称。
我遇到的问题是除了 taglist 中的每个循环之外的所有问题。由于某种原因,它没有收到道具 tagList
。任何帮助将不胜感激。
index.svelte
<script context="module">
export function preload({ params }, { user }) {
let [id, slug] = [params.id, params.slug];
return { id, slug };
}
</script>
<script>
import Editor from "../../../_components/Editor.svelte";
import Topics from "./Topics.svelte";
import { stores } from "@sapper/app";
export let id;
export let slug;
const { session } = stores();
</script>
<svelte:head>
<title />
</svelte:head>
<div class="editor-page">
<div class="container page">
<div class="row">
<div class="col-md-8 offset-md-2 col-xs-12">
<Topics {id} {slug} />
{#if $session.user}
<Editor />
{/if}
</div>
</div>
</div>
</div>
Topics.svelte
<script>
import { onMount } from "svelte";
import * as api from "api.js";
import "bytemd/dist/index.min.css";
import TagList from "../../../_components/_TagList.svelte";
export let id;
export let slug;
let topics = [];
let title = "";
let tagList = [];
let value = "";
let Viewer = null;
onMount(async () => {
const bytemd = await import("bytemd");
Viewer = bytemd.Viewer;
const response = await api.get(
`t/${id}/${slug}`,
localStorage.getItem("jwt")
);
console.log(response);
if (response.topic) {
topics = response.topic;
title = response.title;
value = topics[0].description;
for(let i= 0; i < response.tags.length; i++) {
tagList.push(response.tags[i]);
}
}
});
</script>
<div>
<h3>{title}</h3>
<hr/>
<svelte:component this={Viewer} {value} />
<TagList {tagList} />
</div>
_TagList.svelte
<script>
export let tagList;
console.log(tagList);
</script>
<ul>
{#each tagList as tag}
<p>hello</p>
<li>{tag.name}</li>
{/each}
</ul>
在 Svelte 中,更新仅通过分配触发。
在您的情况下,这意味着当呈现组件时,它将呈现一个空的标签列表 (tagList = []
)。
现在在 onMount
中您执行 taglist.push
,但如前所述,这不会触发更新(请记住此函数在 after 后调用该组件已安装)因为它不是一个分配。
有四种方法可以解决您的问题:
- 在执行 for 循环后
tagList = tagList
,这是一个赋值,将触发更新。 - 不要执行 for 循环,而是使用映射
tagList = response.tags.map(tag => tag)
- 不是执行 for 循环,而是将标签分散到标签列表中
tagList = [...response.tags]
- 考虑到你无论如何都不对标签做任何事情,而且 tagList 是空的而且你似乎没有任何其他更新方式,直接将标签分配给它
tagList = response.tags
当然你的代码可能会被简化,如果你在将每个标签添加到列表之前实际对它做一些事情,情况 3 和 4 不是好的选择,对于那种情况我会使用 map
选项