【问题标题】:How can I export a function from a Svelte component that changes a value in the component?如何从 Svelte 组件中导出更改组件中的值的函数?
【发布时间】:2020-02-05 19:43:46
【问题描述】:

我有一个名为WastedTime.svelte 的组件,其值为wastedTime。还有一个函数可以将值更改为50(在我的真实代码中,这是一个动画,但这是 Stack Overflow 的简化测试用例)。

为了允许从父级调用子函数,我在 Svelte 文档中使用了 <script context="module">

<script context="module">
    var wastedTime = 0;
    export function changeNumber(){
        console.log('changing number')
        wastedTime = 50
    }
</script>

<script>
    // Putting 'var wastedTime = 0' here doesn't work either
</script>


<h1>Wasted time: {wastedTime}</h1>

父从onMount调用子中的函数:

<script>

    import { onMount } from 'svelte';
    import WastedTime, {changeNumber } from './WastedTime.svelte';

    onMount(() => {
        changeNumber()
    });
</script>

<WastedTime />

问题在于,由于wastedTime&lt;script context="module"&gt; 中被引用,它似乎无法更改wastedTime。导出的函数运行,但wastedTime 保持为0。

Copy of this on Svelte REPL

我尝试过: - 将var wastedTime = 0 放入&lt;script context="module"&gt; - 将var wastedTime = 0 放入&lt;script&gt;

都不行。

如何从 Svelte 组件中导出更改组件中的值的函数?

【问题讨论】:

    标签: javascript svelte svelte-component


    【解决方案1】:

    &lt;script context="module"&gt; 不是响应式的 - 更改此块内的变量不会影响单个实例(除非您更改了存储值,并且每个实例都订阅了该存储)。

    相反,直接从实例中导出changeNumber 函数,并使用bind:this 获取对它的引用:

    WastedTime.svelte

    <script>
        var someNumber = 0;
        export function changeNumber(){
            console.log('changing number')
            someNumber = 56
        }
    </script>
    
    <h1>Wasted time: {someNumber}</h1>
    

    App.svelte

    <script>
        import { onMount } from 'svelte';
        import WastedTime from './WastedTime.svelte';
    
        let wastedTimeComponent;
    
        onMount(() => {
            wastedTimeComponent.changeNumber()
        });
    </script>
    
    <WastedTime bind:this={wastedTimeComponent} />
    
    

    在这里演示:https://svelte.dev/repl/f5304fef5c6e43edb8bf0d25d634f965

    【讨论】:

    • 谢谢。我发誓我在文档中读过一个示例,上面说 &lt;script context="module"&gt; 是从组件中导出函数所必需的,但我似乎再也找不到它了。
    • t 可以很好地解释 1)“从 context="module" 脚本块导出的任何内容都成为模块本身的导出。”和 2)“更改此块内的变量不会影响个别实例”。我应该使用context="module"script 导出变量吗?
    • 这个问题和答案需要进入 Svelte 文档!在不解释这种模式的情况下,与组件进行通信是一个三环马戏团。
    • 另一种方法是将WastedTimeService.js 中的函数与exported 函数或作为单独的js 类分开。这种持续性使得对功能进行单元测试变得更加容易。
    【解决方案2】:

    嗯,这是一个该死的好问题!

    我的第一次尝试:

    我已经尝试过@Rich Harris 的回答(从组件中导出一个函数,在将组件与onMount 事件侦听器一起使用时绑定它)。这个概念确实很可靠,但我的问题有点复杂——我试图传递一个带有参数的事件,以便从外部调用。是的 - 这个参数是使用 {#await}.. 伪造的。所以......这种方法不走运


    我的第二次尝试:

    在了解了有关 svelte 如何处理事件的更多信息(我是 svelte 的新手并随着我的进步而学习)之后,我发现了 this 很棒的文章。简而言之:让我们的组件真正面向事件!在你的问题中 - 你实际上试图实现onload 事件......所以......为什么我们不应该这样做?

    component.svelte

    <script>
      import { createEventDispatcher, onMount } from 'svelte';
      const dispatch = createEventDispatcher();
    
      function doSomething() { console.log('wowza!') }
      
      // wait for onMount to trigger, then dispatch event named "load"
      onMount(() => dispatch('load', 
      { 
        data: 'yay',
        doSomething
      }));
    </script>
    

    app.svelte

    <script>
      import { Component } from './component.svelte';
    
      function component_load(event)
      {
        console.log(event.detail.data);
        event.detail.doSomething();
      }
    </script>
    <Component on:load={component_load} />
    

    所以 - 是的,我今天学到了一些东西!另外:

    • 这是一种更优雅的编码方式(事件驱动)
    • 组件通过正确使用 Svelte 事件生命周期来暴露自己
    • dispatch 可以触发以响应其他事件 - 让您为组件构建完整的生命周期

    太棒了!

    【讨论】:

      【解决方案3】:

      里奇回答的简化版:

      App.svelte

      <script>
      import Time from './Time.svelte';
      
      let timeComponent;
      let time;
      </script>
      
      <Time bind:this={timeComponent} bind:time />
      
      <h1>Spent time: {time} ms</h1>
      
      {#if timeComponent}
        <button on:click={() => timeComponent.spendTime() }>Click me</button>
      {:else}
        Loading...
      {/if}
      

      Time.svelte

      <script>
      export var time = 0;
      export function spendTime() {
        time += 50;
      }
      </script>
      

      这里的关键是export function

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-03
        • 2022-01-02
        • 2020-10-26
        • 2019-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-11
        相关资源
        最近更新 更多