0

0

Svelte 5 中的“助手”变量

碧海醫心

碧海醫心

发布时间:2024-11-10 08:03:01

|

464人浏览过

|

来源于dev.to

转载

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() 符文。

SuperCms在线订餐系统
SuperCms在线订餐系统

模板采用响应式设计,自动适应手机,电脑及平板显示;满足单一店铺外卖需求。功能:1.菜单分类管理2.菜品管理:菜品增加,删除,修改3.订单管理4.友情链接管理5.数据库备份6.文章模块:如:促销活动,帮助中心7.单页模块:如:企业信息,关于我们更强大的功能在开发中……安装方法:上传到网站根目录,运行http://www.***.com/install 自动

下载
<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

<script>
    import icon from '../components/icon.svelte';
    import { enhance } from '$app/forms';
    import { tick } from 'svelte';

    export let form;
    export let searchinglang;
    export let l;

    let results = [];
    let previoussearch = '';
    let searchterm;
    let skip;

    $: if (!!form && form?.thereismore) {
        searchterm = form.searchterm;
        skip = number(form?.skip) + 20;
    }

    $: if (!!form?.searchresultfromaction) {
        if (previoussearch == form.searchterm && form.therewasmore) {
            results = [...results, ...form.searchresultfromaction];
        } else {
            results = [...form.searchresultfromaction];
            previoussearch = form.searchterm;
        }
    }

    async function intoview(el) {
        await tick();
        if (el.attributes.index.nodevalue == skip - 20 && skip != undefined) {
            el.scrollintoview({ behavior: 'smooth' });
        }
    }
</script>

{#if results.length}
    <ol>
        {#each results as item, index}
            <li use:intoview {index} aria-posinset={index}>
                <!-- users without javascript have calculated order of results within paggination and css disables standard ol ul numbering -->
                <!-- users with javascript have standard ol ul numbering and loading more feature -->
                <noscript>{number(index) + 1 + number(form?.skip)}. </noscript>
                <a href="/act/{searchinglang}/{item.id}/present/text">{item.title}</a>
            </li>
        {/each}
    </ol>

    {#if form?.thereismore}
        <form
            method="post"
            action="?/search&skip={skip}&therewasmore={form?.thereismore}"
            use:enhance
            autocomplete="off"
        >
            <label>
                <!-- probably we do not need to bind the value as this is hidden input -->
                <!-- <input name="searchterm" type="hidden" bind:value={searchterm} /> -->
                <input name="searchterm" type="hidden" value={searchterm} />
            </label>
            <button aria-label="button to load more search results" class="outline">
                <icon name="loadmore" />
            </button>
        </form>
    {/if}
{:else if form?.searchresultfromaction.length == 0}
    {l.noresultsfound}
{/if}

<style>
    @media (scripting: none) {
        /* users without javascript have calculated order of results within paggination and css disables standard ol ul numbering
users with javascript have standard ol ul numbering and loading more feature */
        ol {
            list-style-type: none;
        }
    }
</style>

苗条5

<script>
    import Icon from '../components/Icon.svelte';
    import { enhance } from '$app/forms';
    import { tick } from 'svelte';

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

    let previousSearch = '';
    let skip = $derived.by(() => {
        if (!!form && form?.thereIsMore) {
            return Number(form?.skip) + 20;
        }
    });

    let helperResultsArr = [];
    let results = $derived.by(() => {
        if (!!form?.searchResultFromAction) {
            if (previousSearch == form.searchTerm && form.thereWasMore) {
                helperResultsArr.push(...form.searchResultFromAction);
                return helperResultsArr;
            } else {
                helperResultsArr = [];
                helperResultsArr.push(...form.searchResultFromAction);
                previousSearch = form.searchTerm;
                return helperResultsArr;
            }
        } else return [];
    });

    async function intoView(el) {
        await tick();
        if (el.attributes.index.nodeValue == skip - 20 && skip != undefined) {
            el.scrollIntoView({ behavior: 'smooth' });
        }
    }
</script>

{#if results.length}
    <ol>
        {#each results as item, index}
            <li use:intoView {index} aria-posinset={index}>
                <!-- users without javascript have calculated order of results within paggination and css disables standard ol ul numbering -->
                <!-- users with javascript have standard ol ul numbering and loading more feature -->
                <noscript>{Number(index) + 1 + Number(form?.skip)}. </noscript>
                <a href="/act/{searchingLang}/{item.id}/present/text">{item.title}</a>
            </li>
        {/each}
    </ol>

    {#if form?.thereIsMore}
        <form
            method="POST"
            action="?/search&skip={skip}&thereWasMore={form?.thereIsMore}"
            use:enhance
            autocomplete="off"
        >
            <label>
                <input name="searchTerm" type="hidden" value={form.searchTerm} />
            </label>
            <button aria-label="Button to load more search results" class="outline">
                <Icon name="loadMore" />
            </button>
        </form>
    {/if}
{:else if form?.searchResultFromAction.length == 0}
    {l.noResultsFound}
{/if}

<style>
    @media (scripting: none) {
        /* users without javascript have calculated order of results within paggination and css disables standard ol ul numbering
users with javascript have standard ol ul numbering and loading more feature */
        ol {
            list-style-type: none;
        }
    }
</style>

现在就这些了。

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

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
go语言闭包相关教程大全
go语言闭包相关教程大全

本专题整合了go语言闭包相关数据,阅读专题下面的文章了解更多相关内容。

143

2025.07.29

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

523

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

412

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

553

2023.08.03

js是什么意思
js是什么意思

JS是JavaScript的缩写,它是一种广泛应用于网页开发的脚本语言。JavaScript是一种解释性的、基于对象和事件驱动的编程语言,通常用于为网页增加交互性和动态性。它可以在网页上实现复杂的功能和效果,如表单验证、页面元素操作、动画效果、数据交互等。

5666

2023.08.17

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

491

2023.09.01

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

216

2023.09.04

Js中concat和push的区别
Js中concat和push的区别

Js中concat和push的区别:1、concat用于将两个或多个数组合并成一个新数组,并返回这个新数组,而push用于向数组的末尾添加一个或多个元素,并返回修改后的数组的新长度;2、concat不会修改原始数组,是创建新的数组,而push会修改原数组,将新元素添加到原数组的末尾等等。本专题为大家提供concat和push相关的文章、下载、课程内容,供大家免费下载体验。

240

2023.09.14

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

561

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.9万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.4万人学习

CSS教程
CSS教程

共754课时 | 32.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号