作者是 Rich Harris,也就是 Ractive, Rollup 和 Buble 的作者,堪称前端界的轮子哥
现在又带来新轮子了!这个框架的 API 设计是从 Ractive 那边传承过来的(自然跟 Vue 也非常像),但这不是重点。
Svelte 的核心思想在于『通过静态编译减少框架运行时的代码量』。
举例来说,当前的框架无论是 React Angular 还是 Vue,不管你怎么编译,使用的时候必然需要『引入』框架本身,也就是所谓的运行时 (runtime)。
但是用 Svelte 就不一样,一个 Svelte 组件编译了以后,所有需要的运行时代码都包含在里面了,除了引入这个组件本身,你不需要再额外引入一个所谓的框架运行时!当然,这不是说 Svelte 没有运行时,但是出于两个原因这个代价可以变得很小:
svelte有一个很明显的不同就是使用了真实的DOM,没有虚拟DOM,这一点令我很诧异
难道前端框架是个圈?
兜兜转转又回来了
于是按照官网的指南,加上自己的翻译理解,写了一份入坑指南
工程化使用
Svelte 官网上提供了2种使用方式
这里我使用了第一种,在这个地址中svelte.dev/repl/hello-…直接下载一个现成的工程项目
解压后进入根目录
cd svelte-app
npm install
复制代码
上面就是svelte官网上下载的默认项目内容
接着运行
npm run dev
复制代码
运行后默认监听5000端口
打开编辑器进入src目录,有个默认的App.svelte
文件,内容如下
<script>
let name = 'world';
</script>
<h1>Hello {name}!</h1>
复制代码
浏览器运行效果如下
基本语法
svelte里面的文件是以文件名.svelte
的形式创建的
一个.svelte
文件的js代码需要在script
标签中, 样式写在style
标签中, html结构独立于二者之外
<script>
</script>
<div>
</div>
<style>
<style/>
复制代码
变量的使用
变量需要用{}
包裹,也可以在里面使用语句和表达式
<script>
let name = 'world';
</script>
<h1>Hello {name}!</h1>
<h1>Hello {name.toUpperCase()}!</h1>
复制代码
样式的使用
css样式需要写在style
标签中
<script>
let name = 'world';
</script>
<h1>Hello {name}!</h1>
<style>
h1{
color:#777
}
</style>
复制代码
动态属性
这一点和vue的v-bind很类似,对于标签的属性也可以动态绑定
<script>
let src = 'tutorial/image.gif';
let name = 'Rick Astley';
</script>
<img src={src} alt="{name} dances.">
复制代码
当然svelte也提供了语法糖,属性名和变量名一样时可以这样写
<img {src} alt="{name} dances.">
复制代码
组件化
svelte也可以使用.svelte
文件作为子组件
在components文件夹中新建一个Child.svelte
文件,在App.svelte
中引入
Child.svelte
<p>This is another paragraph.</p>
复制代码
App.svelte
<script>
import Child from './components/Child.svelte';
</script>
<p>This is a paragraph.</p>
<Child/>
<style>
p {
color: purple;
font-family: 'Comic Sans MS', cursive;
font-size: 2em;
}
</style>
复制代码
效果如下
Reactivity 反应性
svelte的核心系统就是“反应性”,它能使 DOM 与您的应用程序状态保持同步
这里使用一个按钮的点击事件来演示反应性
<script>
let count = 0;
//定义一个累加函数
function incrementCount() {
count += 1;
}
</script>
//svelte的事件绑定方式,后面会说到
<button on:click={incrementCount}>
点了 {count} 次}
</button>
复制代码
点击按钮“+1”,DOM会同步更新
Declarations 声明
当组件的状态发生变化时,Svelte 会自动更新 DOM。
但有时候,组件的某些状态需要根据其他状态来计算,例如根据姓氏和名字计算出全名
这个时候我们可以使用 声明 reactive declarations
使用$:
定义一个声明
<script>
let firstName="西门"
let lastName="吹雪"
$:fullName=firstName+lastName
</script>
<p>全名是{fullName}</p> //西门吹雪
复制代码
$:
看起来很陌生,不像是js代码,其实这个很类似vue中的watch和computed属性
svelte会将$:
解释为 “只要引用的任何值发生变化就重新运行此代码”
所以上面,当声明fullName引用的姓氏和全名有一个发生变化时,fullName就会自动更新
其实,我们完全可以在DOM中直接使用
<p>{firstName+lastName}</p>
复制代码
来代替一个声明
但当我们使用声明比较多时,比如频繁的计算一个数的倍数
<script>
let count = 0;
$: doubled = count * 2;
</script>
<p>{count} 的倍数是 {doubled}</p>
复制代码
这个时候,声明就方便很多。
此外,声明可以是任意语句。 例如,我们可以在 count 发生变化时记录它的值:
在里面可以使用条件判断和常见的输出语句
$: console.log(`the count is ${count}`);
$: {
console.log(`the count is ${count}`);
alert(`I SAID THE COUNT IS ${count}`);
}
复制代码
甚至可以是一个条件判断
<script>
let count = 0;
$: if (count >= 10) {
alert(`当前数值过大`);
console.log(`the count is ${count}`);
count = 9;
}
function handleClick() {
count += 1;
}
</script>
<button on:click={handleClick}>
点了 {count} 次
</button>
复制代码
更新数组和对象的值
因为 Svelte 的反应性是由赋值触发的,所以使用 push 和 splice 等数组方法不会自动导致更新。
比如下面的,我们点击让数组长度+1,但不会有任何变化
<div>
<button on:click={addArr}> 数组长度加1</button>
<p>arr的长度是{arr.length}</p>
</div>
<script>
let arr=[1,2,3,4]
function addArr(){
arr.push(arr.length+1)
}
</script>
复制代码
解决的办法是重新赋值
function addArr(){
arr[arr.length]=arr.length+1
}
复制代码
简单点可以使用ES6的延展操作符
function addArr(){
arr=[...arr, arr.length+1]
}
复制代码
这里有一个简单的口诀:更新变量的名称必须出现在赋值的左侧。
Props 组件传值
在任何实际应用程序中,都需要将数据从一个组件向下传递到其子组件。 为此,我们需要声明属性,通常缩写为“props”。
在 Svelte 中,我们使用 export 关键字来声明一个props
新建一个Child.svelte
<div>
<h3>传递来的名字:{propsName}</h3>
<p>{propsConfig.name}</p>
<p>{propsConfig.age}</p>
<p>{propsConfig.male}</p>
</div>
<script>
//声明一个有默认值的props,类型为string
export let propsName="zds"
//声明一个没有默认值的props
export let propsConfig;
</script>
复制代码
然后再App.svelte中引用,并传值
<script>
import Child from "./component/Child.svelte"
let name="皮卡丘"
let config={
name:"svelte",
age:5,
sex:"male"
}
</script>
<div>
<Child propsName={name} propsConfig={config}/>
</div>
复制代码
当子组件里面的props较多时,比如
Info.sveltr
<script>
export let name
export let age
export let sex
export let phone
export let address
</script>
复制代码
在传值的时候可以使用延展操作符...
<script>
import Info from "./component/Info.svelte"
let infos={
name:"皮卡丘",
age:22,
sex:"male",
phone:"0225-78737",
address:"江苏 苏州"
}
</script>
<Info {...infos}/>
复制代码
但要保证传递对象的属性名和子组件暴露的props名一致
后面持续更新中 2021年7月9日16:46:16