Svelte
Svelte 是一种全新的构建用户界面的方法。
传统框架如 React 和 Vue 在浏览器中需要做大量的工作,而 Svelte 将这些工作放到构建应用程序的编译阶段来处理
- 减少代码量:重复利用你所掌握的编程语言 - HTML、CSS 和 JavaScript,构建的组件无需依赖模板文件。
- 无虚拟 DOM:Svelte 将你的代码编译成体积小、不依赖框架的普通 JS 代码,让你的应用程序无论启动还是运行都变得迅速。
- 真正的反应能力:无需复杂的状态管理库,Svelte 为 JavaScript 自身添加反应能力。
优点:
一、打包体积更小
同样应用的体积:
Svelte 在打包会将引用到的代码打包起来,而没引用过的代码将会被过滤掉,打包时不会加入进来。
二、不使用 Virtual DOM
无需虚拟 DOM 也可进行响应式数据驱动
Svelte 会监听顶层组件所有变量,一旦某个变量发生变化,就更新使用过该变量的组件。这就仅仅只需更新受影响的那部分DOM元素,而不需要整个组件更新。
三、更便捷的响应式绑定
在 React 中,如果需要更新数据并在视图中响应,需要使用 setState 方法更新数据。
在 Vue2 中,响应式数据要放在 data 里,在 methods 中使用 this.xxx 来更新数据。
在 Vue3 的 Composition API 语法中,需要使用 ref 或者 reactive 等方法包裹数据,使用 xxx.value 等方式修改数据
svelte:
<h1>{name}</h1>
<script>
let name = '张三'
setTimeout(() => {
name = '李四'
}, 1000)
</script>
缺点:
- Svelte 的生态不够丰富
- props 是可变的(也属于优点,props 也是可以响应式的),props 目前无法验证类型
生命周期
生命周期是指项目运行时,指定时期会自动执行的方法。
Svelte 中主要有以下几个生命周期:
- onMount: 组件挂载时调用。
- onDestroy: 组件销毁时执行。
- beforeUpdate: 在数据更新前执行。
- afterUpdate: 在数据更新完成后执行。
- tick: DOM元素更新完成后执行。
以上生命周期都是需要从 svelte 里引入的。
起步
# 1、下载模板的命令
npm init vite@latest
# 2、输入项目名
# 3、选择 Svelte 模板
# 4、进入项目并安装依赖
npm install
# 5、运行项目
npm run dev
# 6、在浏览器访问 http://127.0.0.1:5173/
index.html
、src/main.js
和 src/App.svelte
这三个是最主要的文件。
index.html
是项目运行的入口文件,它里面引用了 src/main.js
文件。
基本用法
插值
<script>
let count = 1
function setCount(){
count += 1
}
</script>
<div>
{count}
<button on:click={setCount}>计数</button>
</div>
<style>
div{
font-size: 40px;
}
</style>
表达式
<div>{a} + {b} = {a + b}</div>
属性绑定
<div title={name}>Hello</div>
渲染 HTML 标签 @html
<div>{@html h1El}</div>
样式绑定
<div style="color: {color}">行内样式</div>
<div class:active={foo}>绑定class</div>
基础条件判断
{#if 条件判断}
...
{/if}
列表渲染
{#each expression as name}
...
{/each}
如果元素是对象,可以解构
<script>
let list = [
{name: '张三'},
{name: '李四'}
]
</script>
<ul>
{#each list as {name}}
<li>{name}</li>
{/each}
</ul>
$: 声明反应性
<script>
let count = 0;
$: doubled = count * 2;
function handleClick() {
count += 1;
}
</script>
<button on:click={handleClick}>
点击加1
</button>
<p>{count} 翻倍后 {doubled}</p>
异步渲染 #await
<script>
const api = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('请求成功,数据是xxxxx')
}, 1000)
})
</script>
{#await api}
<span>Loading...</span>
{:then response}
<span>{response}</span>
{:catch error}
<span>{error}</span>
{/await}
组件通讯
父传子
父组件:
<script>
import Phone from './Phone.svelte'
</script>
<div>子组件 Phone 的内容:</div>
<Phone number="88888888" />
子组件:
<script>
export let number = '13266668888'
</script>
<div>电话:{number}</div>
子传父
父组件:
<script>
import Phone from './Phone.svelte'
function print(data) {
console.log(`手机号: ${data.detail}`)
}
</script>
<div>子组件 Phone 的内容:</div>
<Phone on:printPhone={print} />
子组件:
<script>
import { createEventDispatcher } from 'svelte'
const dispatch = createEventDispatcher()
function printPhone() {
dispatch('printPhone', '13288888888')
}
</script>
<button on:click={printPhone}>输出手机号</button>
原理
svelte 的源码由两大部分组成,compiler 和 runtime。compiler 的作用是将 svelte 模版语法编译为浏览器能够识别的js SvelteComponent,而 runtime 则是在浏览器中帮助业务代码运作的运行时函数。
complier
Svelte,在 complier 阶段完成了大部分的工作,而 complier 又分为 parse 和 complie 两部分:
parse
parse 会读取 .svelte 文件的内容进行解析。
complie
Complie 首先会将 parse 过程中拿到的语法树(包含 html,css,instance 和 module)转换为 Component,然后在 render_dom 中通过 code-red 中的 print 函数将component 的转换为 js 可运行代码,最终输出 complier 的结果。
runtime
<h1>{count}</h1>
<script>
let count = 0;
</script>
这段代码经由编译器编译后产生如下代码,包括三部分:
- create_fragment方法
- count的声明语句
- class App的声明语句
// 省略部分代码…
function create_fragment(ctx) {
let h1;
return {
c() {
h1 = element("h1");
h1.textContent = `${count}`;
},
m(target, anchor) {
insert(target, h1, anchor);
},
d(detaching) {
if (detaching) detach(h1);
}
};
}
let count = 0;
class App extends SvelteComponent {
constructor(options) {
super();
init(this, options, null, create_fragment, safe_not_equal, {});
}
}
export default App;
create_fragment
他是编译器根据App的UI编译而成,提供该组件与浏览器交互的方法,在上述编译结果中,包含3个方法:
- c,代表create,用于根据模版内容,创建对应DOM Element
- m,代表mount,用于将c创建的DOM Element插入页面,完成组件首次渲染
- d,代表detach,用于将组件对应DOM Element从页面中移除
总结:
svelte 继前端三大框架之后推陈出新,以一种新的思路实现了响应式,由于起步时间不算很长,目前来说其生态还不够完备, 在大型项目中的应用目前也还有待考究,但是在一些简单页面如活动页、静态页等场景感觉目前还是十分适合的,个人对其未来发展表示看好。
由于其简洁的语法以及与 vue 语法相似的特点,上手成本十分小,感兴趣的可以了解一下,丰富自己。