专栏名称: 前端从进阶到入院
我是 ssh,只想用最简单的方式把原理讲明白。wx:sshsunlight,分享前端的前沿趋势和一些有趣的事情。
目录
相关文章推荐
一念行者  ·  修行者是挖金者 ·  昨天  
滴滴代驾服务订阅平台  ·  限时开启|滴滴代驾司服合作伙伴招募 ·  昨天  
惠济发布  ·  玩转元宵节,郑州交警送上观灯指南→ ·  昨天  
惠济发布  ·  玩转元宵节,郑州交警送上观灯指南→ ·  昨天  
51好读  ›  专栏  ›  前端从进阶到入院

Svelte 5.0,又又又出全新响应式 API 了!

前端从进阶到入院  · 公众号  ·  · 2024-10-25 08:00

正文

Svelte 是一个 Web 开发框架,无虚拟 dom,同时提供了许多开箱即用的功能,感兴趣的可以查看 Svelte 文档 [1]

Svelte 前几天发布了最新的 V5.0 大版本,其中最核心的修改就是重构了它的响应式系统。Svelte 把它起名叫做 runes, 所有 runes API 都使用 $ 开头。

今天一起来学习一下全新的 runes 响应式 API。

$state

在旧版本中,直接使用 let 就可以定义一个响应式变量:


<div>
    <button onclick={increment}>Increment With legacybutton>
    <p>Counter With legacy: {counter}p>
div>

在 Svelte5 中,需要使用 $state 来定义响应式变量:


<div>
    <button onclick={increment2}>Increment With newbutton>
    <p>Counter With new: {counter2}p>
div>

那么在 Svelte5 中,旧版写法是否还兼容呢。是这样的,如果你不使用 runes,仍然是可以用旧版写法的。如果同时使用旧版写法和新版写法,就会失去响应式,变成一个普通变量:


<div>
    <button onclick={increment}>Increment With legacybutton>
    <p>Counter With legacy: {counter}p>
div>
<div>
    <button onclick={increment2}>Increment With newbutton>
    <p>Counter With new: {counter2}p>
div>

使用外部 *.svelte.js 中的 runes

在 Svelte5 中,由于有了 runes,你可以在组件中导入外部 *.svelte.js 或者 *.svelte.ts 中的 runes 来使用,这在 Svelte4 中无法做到。

export const rune = $state({
    count21
});

export function increment2() {
    rune.count2++;
}

在 svelte 组件中直接导入就可以了:


<div>
    <button onclick={increment2}>Increment the rune inside jsbutton>
    <p>Counter2: {rune.count2}p>
div>

$derived

$derived 类似于 Vue 中的计算属性:


<div>
    <button onclick={increment}>Increment the new waybutton>
    <p>Counter: {counter}p>
    <p>Counter Times Two: {counterTimesTwo}p>
div>

$state 的其他用法

当然可以用来创建一个对象:

$state.raw 用于创建一个浅层(shallow)响应式对象。这意味着,这个对象是响应式的,但是它的属性不是,你只可以重新设置整个对象来触发响应式。

$state.snapshot 用于获取一个响应式对象的原始类型(非响应式)。

$effect

$effect 类似于 React 的 useEffect ,区别是会自动收集响应式依赖。

$effect.pre 用于在 DOM 更新之前运行代码:

$effect.root 将会创建一个 effect root,它不会在组件卸载时自动释放,你可以手动调用 cleanup() 来释放



<button onclick={() => cleanup()}>Dispose effect.rootbutton>

$props

在 Svelte4 中,使用 export let value 来定义组件 props。

在 Svelte5 中,使用 $props 来定义组件 props。

子组件:



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

父组件:



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

<Child {count} />

父组件点击增加 count,会传给子组件,而子组件点击增加,不会反映给父组件,此时是一个单向的数据流。

使用 $bindable 实现双向绑定

上面说了,默认 props 是单向数据流,子组件无法修改父组件的数据,这也是合理的。

那么我们常见的一些表单实现效果如下,实现一个受控 Input 组件。

子组件定义 onChange props, 把更改后的值通过 onChange 传回去:



<input type="text" {valueonchange={(event) => {
  onChange((event.target as HTMLInputElement).value);
}}/>

父组件传 onChange,接受子组件回传的值:



<Input {valueonChange={(e) => {
  console.log('child changed to', e);
  value = e;
}}/>

熟悉 React 同学看的就很眼熟,我们经常这么写。

而在 Vue 中,有 v-model 可以实现双向绑定。在 Svelte5 中,可以使用 $bindable 实现双向绑定:



<input type="text" bind:value />

父组件中的 value 也被修改了:


<Input bind:value />

$host

$host 是一个高级特性,当组件被编译为自定义元素时,用来获取当前组件的引用,发送自定义事件。

<svelte:options customElement="my-stepper" />

<script>
    function dispatch(type) {
        $host().dispatchEvent(new CustomEvent(type));
    }
script>

<button onclick={() => dispatch('decrement')}>decrementbutton>
<button onclick={() => dispatch('increment')}>incrementbutton>

最后

Svelte5 的 runes $state ,Vue3 的组合式 API ref ,Solid 的 signal createSignal ,Angular Signals signal ,似乎除了 React 都拥抱了 signal ,你觉得这套东西怎么样呢。







请到「今天看啥」查看全文