通过插槽将变量从页面向上传递到 svelte 布局

Pass variable up from page to svelte layout via slot

所以我想不出一种方法来从 <slot>.

中显示的组件向我的 __layout 变量传递一个变量

我尝试了一些方法,在插槽上使用 bind:let:,但它不起作用。我得到 'myvar' is not a valid binding<slot> cannot have directives.
我也尝试导出或不导出布局上的变量,但我真的无法让它工作...

这是我的:

 <!-- __layout.svelte -->
<script>
export let myvar = undefined;
</script>

<main>
  <slot myvar={myvar}></slot>
  <p>Layout myvar: {myvar}</p>  <!-- << This will stay undefined -->
</main>
 <!-- mypage.svelte -->
<script>
import MyComponent from "$lib/my_component.svelte";
export let myvar;
let a_list_of_things = [1,2,3,4]
</script>

<main>
  {#each a_list_of_things as thing}
    <MyComponent bind:myvar={myvar} thing={thing}/>  <!-- The variable is binded here -->
  {/each}
  <p>mypage myvar: {myvar}</p>   <!-- << This will get the good value -->
</main>
 <!-- my_component.svelte -->
<script>
import IconButton from '@smui/icon-button'

export let myvar;
export let thing;
</script>

<div>
  <IconButton class="material-icons" on:click={() => myvar='something'} >
    autorenew
  </IconButton>  <!-- << We change the value on:click here -->

</div>

所以主要目标是在布局级别上有一个等同于 bind:myvar=myvar 的对象(对于 <slot></slot>.

我尝试理解 documentation 关于它的内容,但没有成功,它似乎更多地是关于组件槽而不是布局槽。


我发现 建议在 sapper(sveltekit 的旧名称)中使用商店,不确定它是否与最新版本的 sveltekit 保持同步,这是可行的方法吗?或者还有其他方法吗?

建议使用上下文。你怎么看?


为什么我需要这个?

所以我的应用程序结构如下:

__layout
 ├─ header (menu)
 ├─ my_page (<slot>)
 │   └ my_component (many)
 └ interactive banner

这样显示:

[ Header Menu ]

Content of the page
 - component 1
 - component 2
 - component n

[ Current component: 2 ] << Updated when click on an elem in the component

component 定义交互式横幅应显示的内容。同样点击interactive banner可以改变components

中显示的状态

我在下面给出了一个带有命名插槽的示例,也未命名 ->

在Slot.svelte

<script>
  let content ='lorem'
</script>


<slot name='named-slot' >
{content}
</slot>

在父组件中

<script>
 import Data from './Slot.svelte'
 let newData=' new content'
</script>

 
 <Data>  
 <svelte:fragment slot='named-slot' let:newData={content}>
  {newData} 
 </svelte:fragment>

 </Data>

以及未命名插槽的示例 ->

在Slot.svelte

<script>
      let content ='lorem'
    </script>
    
    <slot  >
    {content}
    </slot>

在父组件中

<script>
 import Data from './Slot.svelte'
 let newData=' new content'
</script>
    
 

 <Data let:newData={content}> 
  {newData}
   </Data>

由于这条横幅消息似乎是全局状态的一部分,因此商店将是一个很好的解决方案。仅当您需要为页面上的不同组件树设置不同的横幅时才需要上下文。

像这样的东西会起作用:

// src/lib/message.js
import { writable } from 'svelte/store';

export default writable('Default message');
<!-- src/routes/__layout.svelte -->
<script>
    import message from '$lib/message';
</script>

<slot />
<p>{$message}</p>

<!-- src/routes/index.svelte -->
<script>
    import message from '$lib/message';

    function update() {
        $message = 'New message';
    }
</script>

<h1>Hello World</h1>

<button on:click={update}>Update message</button>