首页 > web前端 > js教程 > Svelte 5 中的'助手”变量

Svelte 5 中的'助手”变量

DDD
发布: 2024-11-10 08:28:02
原创
950 人浏览过

Svelte 5 中的助手”变量

再见神奇 Svelte 4 $:

在我最近发布 Svelte 5 迁移的经验和注意事项之后,我想重点介绍从 Svelte 4 迁移到 Svelte 5 时的一些技巧和心态的变化。

Svelte 4 使用“神奇的”$: 并让和完成所有繁重的工作以使代码具有反应性。我们还接受了变量重新分配,例如

<script>
let arr = [1, 2, 3]
let value = 4

arr = [...arr, value]
</script>
登录后复制

而不是更新/改变变量的方法,如推送等

我很惊讶能够使用 Svelte 5 重新学习好的旧 JS 模式。

无需一直保持反应

而且我也可能被 Svelte 4 中的 let 宠坏了,没有考虑反应性,如果需要的话它会被包含在内。 但并非所有变量都必须是反应性的。非反应性变量也可以在反应性甚至“传统变异代码”中更新。反应式变量的真正需要是当我们在 UI 中使用它时(当这个变量在 html/页面中呈现并且我们需要它稍后更新时)。

您可能会在 Svelte 5 中遇到错误,例如无法分配给派生状态,在其自己的范围内引用的状态永远不会更新。您的意思是在闭包内引用它吗?或衍生_引用_selfn如果使用 Svelte 4 编码风格,则派生值无法递归引用自身。

辅助变量的示例

看一下这个 Svelte 4 风格的代码示例:

<script>
    let value;
    let derivedArr = []

    $: if (value) {
        derivedArr = [...derivedArr, value]
    }

    function random () {
        value = Math.floor(1 + Math.random() * 10)
    }
</script>

<button on:click="{random}">Generate Random Value</button>
<p>value: {value}</p>
<p>derivedArr: {derivedArr}</p>
登录后复制

演示

我们有两个反应变量,Svelte 4 会自动解决更新问题。我们只需要记住正确的方法是重新分配变量。

在 Svelte 5 中,我们应该思考如何实现相同的结果。我们使用的两个变量还不够,我们还需要一个,即辅助变量。

首选方法是使用 $driven() 符文。

<script>
    let value = $state();
    let helperArr = [];

    let derivedArr = $derived.by(() => {
      if (value) {
                helperArr.push(value);
                return helperArr;
        }
    });

    function random () {
        value = Math.floor(1 + Math.random() * 10)
    }
</script>

<button onclick="{random}">Generate Random Value</button>
<p>value: {value}</p>
<p>derivedArr: {derivedArr}</p>
登录后复制

演示

如果您知道更简单的方法,请告诉我。

还有一个 $effect() 符文方法可以实现相同的效果。它可能看起来更简单,但我们应该尽可能避免效果(主要是 Svetlet 5 效果不在服务器/SSR 上运行)。

<script>
    let value = $state();
    let helperArr = []
    let effectArr = $derived(helperArr);

    $effect.pre(() => {
            if (value) {
              helperArr.push(value)
            }
        })

    function random () {
        value = Math.floor(1 + Math.random() * 10)
    }
</script>

<button onclick="{random}">Generate Random Value</button>
<p>value: {value}</p>
<p>effectArr: {effectArr}</p>
登录后复制

演示

现实生活中的例子

这是我尝试将 Svelte 4 页面直接迁移到 Svelte 5 的示例。我花了一段时间重新思考代码。此页面用作帖子搜索,具有“加载更多”功能(如果用户没有 JS,则添加结果或分页):

苗条4

    从 '../components/Icon.svelte' 导入图标;
    从'$app/forms'导入{增强};
    从'svelte'导入{tick};

    出口许可证表格;
    导出让搜索语言;
    导出让l;

    让结果= [];
    让以前的搜索='';
    让搜索项;
    让我们跳过;

    $: if (!!form && form?.thereIsMore) {
        searchTerm = form.searchTerm;
        跳过=数字(形式?.跳过)20;
    }

    $: if (!!form?.searchResultFromAction) {
        if (previousSearch == form.searchTerm && form.thereWasMore) {
            结果= [...结果,...form.searchResultFromAction];
        } 别的 {
            结果= [...form.searchResultFromAction];
            previousSearch = form.searchTerm;
        }
    }

    异步函数 intoView(el) {
        等待刻度线();
        if (el.attributes.index.nodeValue == 跳过 - 20 && 跳过!= 未定义) {
            el.scrollIntoView({ 行为: '平滑' });
        }
    }
脚本>

{#if 结果.length}
    <ol>
        {#每个结果作为项目,索引}
            <li use:intoview aria-posinset="{index}">
                <!-- 没有 javascript 的用户已经计算了分页中的结果顺序,并且 css 禁用了标准 ol ul 编号 -->
                <!-- 使用 javascript 的用户具有标准的 ol ul 编号和加载更多功能 -->
                <noscript>{数字(索引)1 数字(形式?.skip)}。 无脚本>
                <a href="/act/%7BsearchingLang%7D/%7Bitem.id%7D/present/text">{item.title}</a>
            </noscript>
</li>
        {/每个}
    </ol>

    {#if 形式?.thereIsMore}
        
            
                <!-- 可能我们不需要绑定该值,因为这是隐藏输入 -->
                <!-- <input name="searchTerm" type="hidden" bind:value={searchTerm} /> -->
                
            标签>
            <button aria-label="加载更多搜索结果的按钮">



<p>苗条5<br>
</p>
<pre class="brush:php;toolbar:false">
    从 '../components/Icon.svelte' 导入图标;
    从'$app/forms'导入{增强};
    从'svelte'导入{tick};

    let { form, searchLang, l } = $props();

    让以前的搜索='';
    让skip = $衍生.by(() => {
        if (!!form && form?.thereIsMore) {
            返回 Number(form?.skip) 20;
        }
    });

    让helperResultsArr = [];
    让结果= $衍生.by(() => {
        if (!!form?.searchResultFromAction) {
            if (previousSearch == form.searchTerm && form.thereWasMore) {
                helperResultsArr.push(...form.searchResultFromAction);
                返回helperResultsArr;
            } 别的 {
                helperResultsArr = [];
                helperResultsArr.push(...form.searchResultFromAction);
                previousSearch = form.searchTerm;
                返回helperResultsArr;
            }
        否则返回[];
    });

    异步函数 intoView(el) {
        等待刻度线();
        if (el.attributes.index.nodeValue == 跳过 - 20 && 跳过!= 未定义) {
            el.scrollIntoView({ 行为: '平滑' });
        }
    }
脚本>

{#if 结果.length}
    <ol>
        {#每个结果作为项目,索引}
            <li use:intoview aria-posinset="{index}">
                <!-- 没有 javascript 的用户已经计算了分页中的结果顺序,并且 css 禁用了标准 ol ul 编号 -->
                <!-- 使用 javascript 的用户具有标准的 ol ul 编号和加载更多功能 -->
                <noscript>{数字(索引)1 数字(形式?.skip)}。 无脚本>
                <a href="/act/%7BsearchingLang%7D/%7Bitem.id%7D/present/text">{item.title}</a>
            </noscript>
</li>
        {/每个}
    </ol>

    {#if 形式?.thereIsMore}
        
            
                <input name="searchTerm" type="hidden" value="{form.searchTerm}">>
            标签>
            <button aria-label="加载更多搜索结果的按钮">



<p>现在就这些了。 </p>

<p>PS:如果您愿意以不同的方式进行迁移,请随时告诉我。</p>


          

            
        </button>
登录后复制

以上是Svelte 5 中的'助手”变量的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板