今年最火开源前端框架——Svelte 5正式发布稳定版、彻底重写、新增$语法 、star数近8万

科技   2024-10-27 20:15   上海  

\


经过近 18 个月的开发,数十名贡献者提交了数千次代码,Svelte 5 终于发布了稳定版,这是该项目历史上最重要的版本。

Svelte 是一款类似 React、Vue 的前端 UI 框架。

如名字所言, Svelte 的体积非常小,其作者 Rich Harris 表示,他设计 Svelte 的核心思想在于“通过静态编译减少框架运行时的代码量”。

Svelte 5 是一次彻底的重写:开发的应用将变得更快、更小、更可靠同时将能够编写更一致、更符合语法习惯的代码。对于框架的新手来说,需要学习的东西更少。

值得关注的是,Svelte 几乎完全向后兼容 Svelte 4,也就是说初始升级将完全无缝:

Svelt 官方介绍,随着越来越多的人使用 Svelte 构建更多、更大的应用程序,最初的一些设计决策的局限性开始变得更加明显。

例如,在 Svelte 4 中,响应性完全由编译器驱动。如果在 Svelte 4 中更改响应对象的单个属性,则整个对象将失效,因为这是编译器实际能做的全部。

与此同时,其它框架采用了基于信号的细粒度响应性,超越了 Svelte 的性能。

同样,Svelte 4 中的组件组合也比较尴尬,主要是因为它将事件处理程序和“插槽内容” (slotted content) 视为独立的概念,与传递给组件的 props 不同。

这是因为在 2019 年,Web 组件似乎很有可能成为组件的主要分发机制,而 Svelte 希望与平台保持一致。现在看,这其实是一个错误选择。

虽然 $ 的构造响应式重新运行语句是一个巧妙的技巧,但结果却是徒劳无功。它混淆了两个本应分开的概念(派生状态和副作用),而且由于依赖关系是在语句编译时而不是运行时确定的,因此它无法重构,搞得越来越复杂。

Svelte 5 消除了这些不一致和麻烦。它引入了 runes,这是一种显式机制,用于声明响应式状态(当然它还有其它作用):

与状态的交互没有改变:与其它框架不同,count 只是一个数字,而不是一个函数,或者具有值属性的对象,或者只能通过相应的 setCount 来更改的东西。

function increment() {
count += 1;
console.log({ count });
}

runes 可以在 .svelte.js 和 .svelte.ts 模块中使用,除了 .svelte 组件,这意味着可以使用单一机制创建可重用的响应式逻辑。

事件处理程序现在就像其它属性一样,比如可以很容易知道组件用户是否提供了特定的事件处理程序(这对于避免昂贵的设置工作非常有用),或者将任意事件处理程序传播到某个元素上,这些对库作者尤其重要。

用于在组件之间传递内容的插槽机制,以及令人困惑的 let: 和 <svelte:fragment> 语法,已被 {#snippet …} 替代,这是一个更强大的工具。

除了这些变化,还有无数改进:原生 TypeScript 支持(不再需要预处理器!)、许多错误修复,以及整体性能和可扩展性的提升。

此外,随着 Svelte 的新版本发布,也推出了新的命令行界面 (CLI),sv。而利用新的 Svelte 5 特性的 SvelteKit,也在计划中了。
详情查看官方公告:https://svelte.dev/blog/svelte-5-is-alive

最后看看 Svelte 5 重要的语法更新:
Runes - 符文
本次最重要的更新,当 Runes 莫属,这是关于变量定义和效果管理的内容。

Svelte v4 的响应式写法:

<script>
    let count = 0;
</script>

<button onclick={() => count++}>
    clicks: {count}
</button>
Svelte v5 的响应式写法:
<script>
    let count = $state(0);
</script>

<button onclick={() => count++}>
    clicks: {count}
</button>
哈哈,是不是新语法有一种 Vue 的既视感?
正所谓,万法归一,殊途同归。
那么不仅如此,类似这样的语法,大概有这么些:

• $state

• $state.raw

• $state.snapshot

• $derived

• $derived.by

• $effect

• $effect.pre

• $effect.tracking

• $effect.root

• $props

• $bindable

• $inspect

• $host

这不禁让我回想起了 10 年前写 PHP 的时候,满屏幕的 $ 的日子。。。

不过还是那句话,习惯就好,我喜欢新语法,喜欢 $
Snippets - 片段
片段的主要作用,就是让你少写重复代码。
笔者看到这个,只感觉两行感动的热泪流了下来 😭。
Vue 中的类似功能是这样的:
<script setup>import{ createReusableTemplate } from '@vueuse/core'; const[DefineTemplate,ReuseTemplate]= createReusableTemplate();</script>
<template>
<DefineTemplate>
<!-- something complex --></DefineTemplate>
<dialogv-if="showInDialog">
<ReuseTemplate/></dialog>
<divv-else>
<ReuseTemplate/></div>
</template>
Svelte v4 的写法:
{#each images as image}
{# if image.href}
<a href={image.href}>
<figure>
                <img
                    src={image.src}
                    alt={image.caption}
                    width={image.width}
                    height={image.height}
                />

                <figcaption>{image.caption}</figcaption>
            </figure>
</a>
{:else}
<figure>
<img
                src={image.src}
                alt={image.caption}
                width={image.width}
                height={image.height}
            />

<figcaption>{image.caption}</figcaption>
</figure>
{/if}
{/each}
Svelte v5 的写法:
{#snippet figure(image)}
<figure>
<img
            src={image.src}
            alt={image.caption}
            width={image.width}
            height={image.height}
        />

<figcaption>{image.caption}</figcaption>
</figure> {
/snippet}

{#each images as image}
{#if image.href}

<a href={image.href}>
    {@renderfigure(image)}
</a>
{:else}
{@renderfigure(image)}
{/if}
{/each}
代码是人在写,人在看,电脑只是执行一串二进制。
写法上的提升,对于编程体验的影响是非常大的,代码应该优先服务于人,其次才服务于机器。
这种编程体验的改变,不亚于钓鱼佬钓到一条重达 2 两的大鲫鱼的快感。
Event handlers - 事件处理
Svelte v4 单事件的写法
<script>
    let count = $state(0);
</script>

<button on:click={() => count++}>
    clicks: {count}
</button>
Svelte v5 单事件的写法
<script>
    let count = $state(0);
</script>

<button onclick={() => count++}>
    clicks: {count}
</button>
Svelte v4 多事件的写法
<button on:click={one} on:click={two}>
    ...
</button>
Svelte v5 多事件的写法
<button
    onclick={(e) =>
 {
        one(e);
        two(e);
    }}
>
    ...
</button>
Svelte v4 事件修饰符的写法
<button on:click|once|preventDefault={handler}>...</button>
Svelte v5 事件修饰符的写法
<script>
functiononce(fn){
    returnfunction(event){
    if(fn) fn.call(this, event);
            fn =null;
    };
}

functionpreventDefault(fn){
    returnfunction(event){
            event.preventDefault();
            fn.call(this, event);
    };
}
</script>

<button onclick = {
once(preventDefault(handler))
} >
... < /button>
事件上面的写法,给我的感觉就是,返璞归真了。
说实话,我喜欢原来的写法。
Imports - 导入
flushSync
<script>
import {
    flushSync 
}from 'svelte';

let count = $state(0);
let element;

functiononclick(){
flushSync(() =>(count +=1));

// without `flushSync`, the DOM would be updated in the future
console.log(element.textContent===String(count));
}
</script>

<span bind: this = {element}>{count}</span>
<button {onclick}>update</button>
mount
import {
mount
} from 'svelte';
importAppfrom './App.svelte';

const app = mount(App, {
target: document.querySelector('#app'),
        props: {some: 'property'}
});
hydrate
import {
hydrate
} from 'svelte';
importAppfrom './App.svelte';

const app = hydrate(App, {
target: document.querySelector('#app'),
        props: {some: 'property'}
});


本文部分内容来自「陈随易」公众号。

1年272个版本后,Svelte v5终于发布了


相关来源

https://svelte.dev/blog/svelte-5-is-alive

https://mp.weixin.qq.com/s/J0fnK5ufOvH9_wyZUPPJ7Q

玩转VS Code
编程开发,业界资讯,以及 VS Code 的热门文章、使用技巧、插件推荐、插件开发攻略等,全部都可以在这里找到。带你玩转 VS Code!
 最新文章