Skip to content

大家好,我是农村程序员,独立开发者,前端之虎陈随易。

个人网站

这是我的个人网站:https://chensuiyi.me,欢迎一起交朋友~


北京时间 2024年10月20日凌晨12点45分, 在持续了 11 个月,发布了 272 个预览版后,Svelte 终于发布了 v5.0.0 正式版。

Svelte v5.0.0发布

在发布后的 6小时内,接近 400 的点赞人数,在所有开源项目中都是首屈一指的,可见大家对这次大版本发布的期待和关注。

为了照顾一下还不了解 Svelte 的读者,笔者对 Svelte 简单科普一下。

Svelte 的作者 Rich Harris

首先介绍一下 Svelte 背后的作者,叫做 Rich Harris,是一位非常有影响力的 JavaScript 开发者和开源贡献者,最初是一名记者和数据可视化专家,曾在英国卫报(The Guardian)和纽约时报(The New York Times)工作。

Svelte 的想法在 2016年 感恩节期间形成,他受到编译器概念的启发,开始开发 Svelte 作为一种 “无框架的框架”

2022年,Rich Harris 加入 Vercel公司,全职开发 Svelte,这一举动使 Svelte 的开发更加稳定和持续。

Svelte 的特点

其次,则是 Svelte 为何有如此大的魔力,让这么多人为其趋之若鹜呢?

以下是 Svelte 的主要特点:

  1. Svelte是一个编译时框架,而不是运行时框架。
    1. 更小的bundle size,因为框架代码不需要在运行时加载。
    2. 更快的运行速度,因为大部分工作在编译时完成。
  2. Svelte使用简洁直观的语法来定义组件和行为。
    1. 降低学习曲线,特别是对于已经熟悉HTML、CSS和JavaScript的开发者。
    2. 提高开发效率,减少样板代码。
  3. Svelte的反应性系统基于简单的赋值操作。
    1. 无需使用特殊的API或方法来触发更新。
    2. 代码更加直观和易于理解。
  4. Svelte直接操作DOM,而不使用虚拟DOM。
    1. 潜在的性能提升,特别是在小型到中型应用中。
    2. 减少内存使用。
  5. Svelte提供了内置的动画和过渡系统。
    1. 易于创建流畅的用户界面。
    2. 无需引入额外的库来处理动画。
  6. Svelte默认提供组件级的样式封装。
    1. 避免样式冲突,无需额外的CSS-in-JS解决方案。
    2. 提高样式管理的可维护性。
  7. 通过SvelteKit,Svelte原生支持服务器端渲染。
    1. 改善首次加载性能和搜索引擎优化(SEO)。
    2. 提供更好的用户体验,特别是在网络连接较慢的情况下。
  8. Svelte生成的代码非常轻量。
    1. 适合性能敏感的应用,如移动web应用。
    2. 减少加载时间,提高用户体验。
  9. Svelte官方支持TypeScript。
    1. 提供类型安全,减少运行时错误。
    2. 改善开发体验,特别是在大型项目中。
  10. Svelte可以轻松集成到现有项目中。
    1. 允许渐进式采用,无需一次性重写整个应用。
    2. 适合both小型组件和大型应用开发。
  11. Svelte的设计理念是使前端开发更加简单和直观。
    1. 新开发者可以快速上手。
    2. 减少团队培训时间和成本。
  12. 尽管相对较新,Svelte已经拥有一个快速增长的社区。
    1. 持续的改进和更新。
    2. 丰富的资源和第三方库。

特点不少,主要是照顾一下第一次了解 Svelte 的读者,可以对其进行一次更全面的认识。

那么对于笔者来说呢,主要是一个特点吸引了我:无运行时

也就是说,使用 Svelte 编译后的代码,不像 Vue 或 React 一样,编译后还有个运行时在里面。

也就是说,我们去看戏,必须得自己带凳子。

Svelte 不一样,直接坐地上,简单方便。

当然,具体的细节,肯定不是这个比喻这么简单,读者可以去查看官网,了解一下更全面的内容。

Svelte v5 版本更新内容

那么本次更新日志,虽然字不多,但是涉及到了 600多个 issue 的处理,可以说是 字少事大 了。

  1. 更好的表现。
  2. 带有符文的更精细的反应系统。
  3. 具有片段和事件属性的更具表现力的模板语法。
  4. 原生 TypeScript 支持。
  5. 并与以前的语法向后兼容!

总结起来一句话:更好,更快,更强

来看看本次更新后的语法

Runes - 符文

本次最重要的更新,当 Runes 莫属,这是关于变量定义和效果管理的内容。

Svelte v4的响应式写法:

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

<button onclick={() => count++}>
	clicks: {count}
</button>

Svelte v5的响应式写法:

javascript
<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 中的类似功能是这样的:

vue
<script setup>
import { createReusableTemplate } from '@vueuse/core';

const [DefineTemplate, ReuseTemplate] = createReusableTemplate();
</script>

<template>
    <DefineTemplate>
        <!-- something complex -->
    </DefineTemplate>

    <dialog v-if="showInDialog">
        <ReuseTemplate />
    </dialog>
    <div v-else>
        <ReuseTemplate />
    </div>
</template>

Svelte v4的写法:

javascript
{#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的写法:

javascript
{#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}>
			{@render figure(image)}
		</a>
	{:else}
		{@render figure(image)}
	{/if}
{/each}

代码是人在写,人在看,电脑只是执行一串二进制。

写法上的提升,对于编程体验的影响是非常大的,代码应该优先服务于人,其次才服务于机器。

这种编程体验的改变,不亚于钓鱼佬钓到一条重达2两的大鲫鱼的快感。

Event handlers - 事件处理

Svelte v4单事件的写法

javascript
<script>
	let count = $state(0);
</script>

<button on:click={() => count++}>
	clicks: {count}
</button>

Svelte v5单事件的写法

javascript
<script>
	let count = $state(0);
</script>

<button onclick={() => count++}>
	clicks: {count}
</button>

Svelte v4多事件的写法

javascript
<button on:click={one} on:click={two}>
    ...
</button>

Svelte v5多事件的写法

javascript
<button
    onclick={(e) => {
        one(e);
        two(e);
    }}
>
    ...
</button>

Svelte v4事件修饰符的写法

javascript
<button on:click|once|preventDefault={handler}>...</button>

Svelte v5事件修饰符的写法

javascript
<script>
	function once(fn) {
		return function (event) {
			if (fn) fn.call(this, event);
			fn = null;
		};
	}

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

<button onclick={once(preventDefault(handler))}>...</button>

事件上面的写法,给我的感觉就是,返璞归真了。

说实话,我喜欢原来的写法。

Imports - 导入

flushSync

javascript
<script>
	import { flushSync } from 'svelte';

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

	function onclick() {
		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

javascript
import { mount } from 'svelte';
import App from './App.svelte';

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

hydrate

javascript
import { hydrate } from 'svelte';
import App from './App.svelte';

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

摘录了几个代码片段,全部更新内容预览在这https://svelte-5-preview.vercel.app

你不能听一个写文章的把知识全学了,作为一个有追求的开发者,还是要经常去研究官方文档。

最后,欢迎关注笔者的网站和公众号,在这里https://chensuiyi.me,可以了解到我的最新内容。

何以解忧,唯有代码。不忘初心,方得始终。