探索Svelte
什么是Svelte
Svelte
本意是苗条纤瘦的,Svelte
是一种构建用户界面的全新方法,它被预测为未来十年可能取代React
和Vue
等其他框架的新兴技术。作者是前端轮子哥 Rich Harris,同时也是 Rollup 的作者。
他设计 Svelte
的核心思想在于『通过静态编译减少框架运行时的代码量』,也就是说,vue
和 react
这类传统的框架,都必须引入运行时 (runtime) 代码,用于虚拟dom、diff 算法。Svelted完全溶入JavaScript,应用所有需要的运行时代码都包含在bundle.js里面了,除了引入这个组件本身,你不需要再额外引入一个运行代码。
从2019年开始, Svelte出现在榜单中。刚刚过去的2020年,Svelte在满意度排行榜中超越了react,跃升到了第一位。
Svelte的优势
从容量大小来看,Vue
58k,React
97.5k,而Svelte
只有9.7k。性能方面略逊Vue
但是强于React
。代码量方面碾压Vue
和React
。同时,Svelte自带数据框架。
Svelte的劣势
- 没有像AntD那样成熟的UI库。
- Svelte 原生不支持预处理器,比如说less/scss。
- Svelte 原生脚手架没有目录划分。
- 暂时不支持typescript,虽然官方说了会支持, 但是不知道什么时候。
Svelte如何处理渲染问题
众所周知,React
采用的虚拟DOM和diff算法来解决渲染问题,但是由于React
采用jsx
语法本质不理解数据代表的意义,没有办法做出优化,因此才会出现诸如pureComponent,shouldComponentUpdate,useMemo,useCallback这些生命周期来控制重复渲染问题。
而Svelte
采用了Templates
语法(类似于Vue
的写法),更加严格和具有语义性,可以在编译的过程中就进行优化操作。1
2
3
4
5
6
7<template>
<div>
<p>{{name}}</p>
<p>8888</p>
<p>8888</p>
</div>
</template>
编译器针对这块template代码可以很清楚地知道哪些代码是会变动,哪些代码不会变动。
Svelte实例代码
- 小demo
App.svelte1
2
3
4
5
6
7<script>
import Button from './button.svelte'
let name = 'world';
</script>
<h1>Hello {name}!</h1>
<Button/>
button.svelte1
2
3
4
5
6
7
8
9
10<script>
let count = 0;
function handleClick() {
count += 1;
}
</script>
<button on:click={handleClick}>
Clicked {count} {count === 1 ? 'time' : 'times'}
</button>
$:
响应式语句
1 | let count = 0; |
在 Svelte
中,以 $:
开头的语句就是响应式语句,Svelte
会自动分析响应式语句所依赖的变量,当依赖变量发生变化时,Svelte
就会重新执行相应的响应式语句。当 Svelte
看到任何带有 $:
前缀的语句时,它就知道要将右边的变量赋值给左边的变量,而不需要使用let
将一个变量的值绑定到另一个变量;并且Svelte
可以以响应式的方式运行任何语句。1
2
3
4
5
6
7
8
9$: console.log(`the count is ${count}`);
$: {
console.log(`the count is ${count}`);
alert(`I SAID THE COUNT IS ${count}`);
}
$: if (count >= 10) {
alert(`count is dangerously high!`);
count = 9;
}
但是Svelte
的响应是基于赋值操作的,数组的 push
、splice
等操作不会触发响应式更新。
- 接收Props
1 | <script> |
生命周期
1
2
3
4
5
6
7
8
9
10
11
12<script>
import { onMount,onDestroy,beforeUpdate,afterUpdate,tick } from 'svelte';
let photos = [];
onMount(async () => {
const res = await fetch(`https://jsonplaceholder.typicode.com/photos?_limit=20`);
photos = await res.json();
});
onDestroy(() => alert('gg'));
</script>逻辑判断
由于HTML没有类似于逻辑判断的语法,因此Svelte
加了个这个东西。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37<script>
let user = { loggedIn: false };
function toggle() {
user.loggedIn = !user.loggedIn;
}
</script>
{#if user.loggedIn}
<button on:click={toggle}>
Log out
</button>
{/if}
{#if !user.loggedIn}
<button on:click={toggle}>
Log in
</button>
{/if}
//或
{#if user.loggedIn}
<button on:click={toggle}>
Log out
</button>
{:else}
<button on:click={toggle}>
Log in
</button>
{/if}
//或
{#if x > 10}
<p>{x} is greater than 10</p>
{:else if 5 > x}
<p>{x} is less than 5</p>
{:else}
<p>{x} is between 5 and 10</p>
{/if}遍历
1
2
3
4
5{#each cats as cat}
<li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
{cat.name}
</a></li>
{/each}await
1
2
3
4
5
6
7{#await promise}
<p>...waiting</p>
{:then number}
<p>The number is {number}</p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await}
- 事件绑定
1
2
3
4
5
6<button on:click|once={handleClick}>
Click me
</button>
<button on:click={handleClick}>
Click me
</button>
自定义事件
1 | <script> |
- Store
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38store.js
import { writable,readable,derived } from 'svelte/store';
export const count = writable(0);//writable类型的store有update和set两种subscribe方法
export const time = readable(new Date(), function start(set) {
const interval = setInterval(() => {
set(new Date());
}, 1000);
return function stop() {
clearInterval(interval);
};
});
//readable无法从外部进行更新,没有set()或update()方法。一旦设置了初始状态,便无法从外部进行修改。
export const elapsed = derived(
time,
$time => Math.round(($time - 100*Math.random()) / 1000)
);
//derived允许您创建依赖于现有存储的值的新存储值
app.svelte
<script>
import { count } from './stores.js';
import Incrementer from './Incrementer.svelte';
import Decrementer from './Decrementer.svelte';
import Resetter from './Resetter.svelte';
let count_value;
const unsubscribe = count.subscribe(value => {
count_value = value;
});
</script>
<h1>The count is {count_value}</h1>
综上。