布局、路由和组件之间的 Sveltekit 通信
Sveltekit communication between layout, routes and components
我正在尝试将 svelte SPA 移至 Sveltekit。
在我的 SPA 中,通信模式就是我所说的“控制器组件”,它负责显示某些组件、侦听它们的事件并相应地更新应用程序。总的来说,它看起来像这样的 REPL:
https://svelte.dev/repl/47bd3f8004624a3c95653b1f1aefd8ee?version=3.46.4
如您在此示例中所见,序列非常简单:
App 状态 1) App 显示 CompA 和 CommonComp
App state 2) CompA刚挂载后触发doSomething函数
应用程序状态 3) 应用程序然后调用 commonComp.setTitle 并显示 CompB 代替 CompA
在 SvelteKit 中,我很难做类似的事情,因为我不明白如何将数据从带插槽的子组件传递到包含插槽的组件,反之亦然。
不管怎样,这让我做出了这样的尝试:
我需要2条路线:
- PageA.svelte 当显示 CompA 和 CommonComp 时
- PageB.svelte CompB & CommonComp 显示时
因为 CommonComp 在每个州始终可见,我认为它应该驻留在 __layout.svelte 文件中。
...这让我看到了下面的草稿,其中的评论解释了我遇到的访问问题。
/src/routes/__layout.svelte
<slot />
<CommonComp />
/src/routes/PageA.svelte
<script>
import { goto } from "$app/navigation";
import CompA from "$lib/CompA.svelte";
function handleDoSomethingFinished() {
goto("/test/pageB");
}
</script>
<CompA on:do_something_finished={handleDoSomethingFinished} />
/src/lib/CompA.svelte
<script>
import { onMount } from "svelte";
import { createEventDispatcher } from "svelte";
const dispatch = createEventDispatcher();
onMount(() => {
setTimeout(() => dispatch("do_something_finished"), 3000);
});
</script>
<p>Component A</p>
/src/routes/PageB.svelte
<script>
import CompB from "$lib/CompB.svelte";
// How to call CommonComp.setTitle function from here ?
</script>
<CompB />
/src/lib/CompB.svelte
<p>Component B</p>
/src/lib/CommonComp.svelte
<script>
let title = "Common Component";
import { createEventDispatcher } from "svelte";
const dispatch = createEventDispatcher();
export function setTitle(t) {
title = t;
dispatch("title-modified");
}
</script>
<p>{title}</p>
我想我可能已经尝试过共享一些商店并将它们的值检查到响应式语句中以触发适当的操作但是当我想到它时,我看到了一堆蠕虫所以我在这里遗漏了一些东西。感谢您的帮助。
这有点复杂。根据 export
上的 Svelte 文档:
If you export a const, class or function, it is readonly from outside
the component. Function expressions are valid props, however.
Readonly props can be accessed as properties on the element, tied to
the component using bind:this syntax.
意味着您必须使用 bind:this
创建对 CommonComp
的引用,然后传递它以便在其上调用 setTitle
方法。这将是向下钻取的支柱,从布局的 slot
向下钻取会带来额外的麻烦。我根本不推荐这样做。
一种方法是利用 load
facility and stuff
,通过在 stuff
object 上设置 属性,例如 ccTitle
PageB 的加载函数,然后在 CommonComp
内订阅 $app/stores
提供的 page
商店以响应式设置标题:
$: title = $page.stuff.ccTitle || "Common Component"
但是,因为你是通过PageB的load
函数设置stuff
,所以不是很灵活(load
是从模块部分 prior 到实际加载的页面执行,因此您无法从实际页面脚本与 stuff
交互。
This 是上述方法的一个简单示例。
最终,你似乎不愿意下去的商店路线将是最简单直接的选择。 title
店铺基础到极致:
import { writable } from 'svelte/store';
const title = writable('Common Component');
export default title;
使用 CommonComp
中的商店也是如此:
<script>
import title from "$lib/stores/title";
</script>
<p>{$title}</p>
从 PageB 设置新标题也是如此:
<script>
import CompB from "$lib/CompB.svelte";
import title from "$lib/stores/title";
$title = "Custom Title";
// or say you wanted to set it reactively based on a 'foo' variable:
// $: $title = foo
</script>
<CompB />
这比上面提到的 load
方法以及 would-be 向下钻取方法要简单和清晰得多。商店 不需要 复杂,并且对跨页面和组件进行交流非常有帮助。
Here 是使用商店方法的简单示例。
更新/编辑:
如果你想封装你常用的组件方法,你也可以使用上面提到的存储方法,但不是存储标题,而是存储对你的 CommonComp
实例的引用,从而提供一个表示从订阅商店的任何页面或组件调用 $commonComp.setTitle()
。
Here 是使用该方法的示例。
组件的结构对于更容易绑定值是最重要的。
我正在尝试将 svelte SPA 移至 Sveltekit。
在我的 SPA 中,通信模式就是我所说的“控制器组件”,它负责显示某些组件、侦听它们的事件并相应地更新应用程序。总的来说,它看起来像这样的 REPL:
https://svelte.dev/repl/47bd3f8004624a3c95653b1f1aefd8ee?version=3.46.4
如您在此示例中所见,序列非常简单: App 状态 1) App 显示 CompA 和 CommonComp App state 2) CompA刚挂载后触发doSomething函数 应用程序状态 3) 应用程序然后调用 commonComp.setTitle 并显示 CompB 代替 CompA
在 SvelteKit 中,我很难做类似的事情,因为我不明白如何将数据从带插槽的子组件传递到包含插槽的组件,反之亦然。 不管怎样,这让我做出了这样的尝试:
我需要2条路线:
- PageA.svelte 当显示 CompA 和 CommonComp 时
- PageB.svelte CompB & CommonComp 显示时
因为 CommonComp 在每个州始终可见,我认为它应该驻留在 __layout.svelte 文件中。
...这让我看到了下面的草稿,其中的评论解释了我遇到的访问问题。
/src/routes/__layout.svelte
<slot />
<CommonComp />
/src/routes/PageA.svelte
<script>
import { goto } from "$app/navigation";
import CompA from "$lib/CompA.svelte";
function handleDoSomethingFinished() {
goto("/test/pageB");
}
</script>
<CompA on:do_something_finished={handleDoSomethingFinished} />
/src/lib/CompA.svelte
<script>
import { onMount } from "svelte";
import { createEventDispatcher } from "svelte";
const dispatch = createEventDispatcher();
onMount(() => {
setTimeout(() => dispatch("do_something_finished"), 3000);
});
</script>
<p>Component A</p>
/src/routes/PageB.svelte
<script>
import CompB from "$lib/CompB.svelte";
// How to call CommonComp.setTitle function from here ?
</script>
<CompB />
/src/lib/CompB.svelte
<p>Component B</p>
/src/lib/CommonComp.svelte
<script>
let title = "Common Component";
import { createEventDispatcher } from "svelte";
const dispatch = createEventDispatcher();
export function setTitle(t) {
title = t;
dispatch("title-modified");
}
</script>
<p>{title}</p>
我想我可能已经尝试过共享一些商店并将它们的值检查到响应式语句中以触发适当的操作但是当我想到它时,我看到了一堆蠕虫所以我在这里遗漏了一些东西。感谢您的帮助。
这有点复杂。根据 export
上的 Svelte 文档:
If you export a const, class or function, it is readonly from outside the component. Function expressions are valid props, however.
Readonly props can be accessed as properties on the element, tied to the component using bind:this syntax.
意味着您必须使用 bind:this
创建对 CommonComp
的引用,然后传递它以便在其上调用 setTitle
方法。这将是向下钻取的支柱,从布局的 slot
向下钻取会带来额外的麻烦。我根本不推荐这样做。
一种方法是利用 load
facility and stuff
,通过在 stuff
object 上设置 属性,例如 ccTitle
PageB 的加载函数,然后在 CommonComp
内订阅 $app/stores
提供的 page
商店以响应式设置标题:
$: title = $page.stuff.ccTitle || "Common Component"
但是,因为你是通过PageB的load
函数设置stuff
,所以不是很灵活(load
是从模块部分 prior 到实际加载的页面执行,因此您无法从实际页面脚本与 stuff
交互。
This 是上述方法的一个简单示例。
最终,你似乎不愿意下去的商店路线将是最简单直接的选择。 title
店铺基础到极致:
import { writable } from 'svelte/store';
const title = writable('Common Component');
export default title;
使用 CommonComp
中的商店也是如此:
<script>
import title from "$lib/stores/title";
</script>
<p>{$title}</p>
从 PageB 设置新标题也是如此:
<script>
import CompB from "$lib/CompB.svelte";
import title from "$lib/stores/title";
$title = "Custom Title";
// or say you wanted to set it reactively based on a 'foo' variable:
// $: $title = foo
</script>
<CompB />
这比上面提到的 load
方法以及 would-be 向下钻取方法要简单和清晰得多。商店 不需要 复杂,并且对跨页面和组件进行交流非常有帮助。
Here 是使用商店方法的简单示例。
更新/编辑:
如果你想封装你常用的组件方法,你也可以使用上面提到的存储方法,但不是存储标题,而是存储对你的 CommonComp
实例的引用,从而提供一个表示从订阅商店的任何页面或组件调用 $commonComp.setTitle()
。
Here 是使用该方法的示例。
组件的结构对于更容易绑定值是最重要的。