Svelte能否使用组合函数?

5

我来自于vue并且习惯使用组合函数。我正在尝试找出在svelte中实现这一点的方法。

因此,我创建了一个js文件,并导入store,然后尝试创建一个函数,以便我可以在多个组件上调用它并单独运行。

swipe.js文件

import { writable, derived, get } from 'svelte/store';

function createSwipe() {

  const dyFromStart = writable(0)

  function moveEvent(eventType, val){
    console.log('moveEvent', eventType, val, get(dyFromStart))
    dyFromStart.update(n => n + 1);
  }

  const dxScore = derived(dyFromStart, $dyFromStart => $dyFromStart + 3)
  const dyScore = derived(dyFromStart, $dyFromStart => Math.round($dyFromStart + 100));
  return {
    moveEvent,
    dxScore,
    dyScore, 
  };
}

export const swipe = createSwipe();

然后在Svelte组件中,在脚本中导入函数并将其分解为子部分。

<script>
import { swipe } from "$lib/swipe";
let { moveEvent, dxScore, dyScore } = swipe
</script>
<p>{$dxScore}{$dyScore}</p>
<button on:click="() => moveEvent">button</button>

最终我希望将其转换为滑动组件,因此命名为“swipe”,但是我正在努力掌握基础知识。因此,我希望能够为每个组件拥有唯一的存储空间,如果我使用多个 .svelte 组件,则所有组件之间的状态会共享。

而不仅仅是三个 modal.svelte 组件,我希望为许多不同的组件使用 swipe,比如一个叫 photoViewer.svelte 的通用滑动函数,并为所有组件使用相同的代码。

或者我只需要在每个 .svelte 组件中像这样保留状态:const dyFromStart = writable(0),并将其传递到一个纯 js 函数中返回结果并更新本地 .svelte 变量?

我将其添加为非存储更纯净的 js 内容,但无法使其具有反应性,因此接受下面关于已验证并且似乎是正确方法的存储方法答案。

export function createSwipe() {
 let dyFromStart = 0

  function moveEvent(eventType, val){
    console.log('moveEvent', eventType, val, dyFromStart, dxScore(), dyScore())
    dyFromStart++
  }

  function dxScore(){ return dyFromStart + 3 }
  // const dzScore = derived(dyFromStart, $dyFromStart => $dyFromStart + 3)
  const dyScore = () => Math.round(dyFromStart + 100)
  
  return {
    moveEvent,
    dxScore,
    dyScore,
    dyFromStart
  };

export function createSwipe() {
let dyFromStart = 0
  let dxScore = dyFromStart + 3
  let dyScore = Math.round(dyFromStart + 100)

  function moveEvent(eventType, val){
    console.log('moveEvent', eventType, val, dyFromStart, dxScore, dyScore)
    dyFromStart++
    dxScore = dyFromStart + 3
    dyScore = Math.round(dyFromStart + 100)
  }

  return {
    moveEvent,
    dxScore,
    dyScore,
    dyFromStart
  };

我想它可以正常工作,只是不具备与$一起反应的功能,如果这样做需要调用更新差异本地变量

就可组合函数类型风格而言,这似乎对我来说是最符合Svelte特性的方式之一,或者类似于此,而不是存储类型。

export function createSwipe() {
 let dyFromStart = 0

  function moveEvent(eventType, val){
    console.log('moveEvent', eventType, val)
    dyFromStart++
  }

  $: dxScore = dyFromStart + 3
  $: dyScore = Math.round($dyFromStart + 100)
  return {
    moveEvent,
    dxScore,
    dyScore, 
  };
}
1个回答

3
我不是完全理解问题,所以我先尝试重述一下我认为你想要的:
  • 你想在多个地方使用你的滑动功能。
  • 每次使用该滑动功能应该独立于其他所有内容。
如果这正确的话,那么答案很简单:不要做 export const swipe = createSwipe()。删除这一部分,而是直接导出create函数以在组件中直接使用。这样每次都会创建一个新的独立实例。
<script>
  import { createSwipe } from "$lib/swipe";
  let { moveEvent, dxScore, dyScore } = createSwipe()
</script>
<p>{$dxScore}{$dyScore}</p>
<button on:click="() => moveEvent">button</button>

太好了,这正是我想要的,谢谢!跟进问题是,代码需要(或建议)使用存储类型变量吗?还是可以使用普通的JS?当我尝试使用普通的JS时,我没有完全弄清楚如何使变量具有响应性,并尝试像$:locDxScore = dxScore或作为var dxScore()一样,但不会具有响应性。如果调用按钮并控制台记录它,它将调用并显示正确的值,但如果可能的话,我宁愿它自动执行。由于我是新手,对于存储内容的所有优缺点都不是100%确定,所以在这里更好还是更差呢? - Jordan
在这种情况下,使用 store 是正确的选择,以便获得所需的响应性、自动更新等功能。 - dummdidumm
我添加了一些非存储的东西,我尝试过但不是响应式的(或者我没有完全正确地做),但好的,听起来存储仍然是最好的选择,谢谢。这通常也是最佳方法吗?就像在.svelte <script>中的let变量是响应式的,但无法将该精确代码(没有存储)移动到外部并以相同的方式响应式地工作。 - Jordan
因为如果我的js代码非常长,那么把所有代码都放在一个文件里不是最理想的,但是也不适合把所有代码转换成存储到外部文件中对吧?似乎应该从外部文件以同样的方式工作,只需要做对就可以了,但也许我错了。 - Jordan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接