【问题标题】:Pass variable up from page to svelte layout via slot通过插槽将变量从页面向上传递到苗条布局
【发布时间】:2022-02-01 00:41:31
【问题描述】:

所以我想不出办法从<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 等效的对象(对于&lt;slot&gt;&lt;/slot&gt;

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


我发现this other question 建议在 sapper(sveltekit 的旧名称)中使用商店,不确定它是否与 sveltekit 的最新版本保持同步,这是要走的路吗?还是有别的办法?

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


我为什么需要这个?

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

__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中显示的状态

【问题讨论】:

    标签: svelte svelte-3 sveltekit


    【解决方案1】:

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

    这样的事情会起作用:

    // 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>
    

    【讨论】:

    • 非常感谢,成功了!你能补充一下背后的魔法吗?我认为了解我们为什么要做这些事情很重要……
    • message.js 我们创建并导出 Svelte 商店。任何组件都可以使用$store 语法导入和订阅商店。当商店更新时,任何订阅该商店的人都会收到通知。这允许我们更新index.svelte 中的存储并自动接收__layout.svelte 中的新值。如果您还没有,我强烈建议您通过 Svelte tutorial on stores,因为它们是一个重要的 Svelte 概念。
    【解决方案2】:

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

    在 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>
    

    【讨论】:

    • 但这不适用于布局,槽是由路线定义的吗?还是我错过了什么?
    猜你喜欢
    • 2018-07-28
    • 2023-03-03
    • 2018-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-05
    • 1970-01-01
    相关资源
    最近更新 更多