前端新宠 Svelte 带来哪些新思想?赶紧学起来!

发表于 1年以前  | 总阅读数:247 次

本文介绍

Svelte[1] 是我用过最爽的框架,就算 Vue 和 React 再强大,生态再好,我还是更喜欢 Svelte,因为它开发起来真的很爽。

其实在很久之前我就注意到 Svelte[2] ,但一直没把这个框架放在心上。

因为我之前的工作主要使用 Vue,偶尔也会接触到一些 React 项目,但完全没遇到过使用 Svelte 的项。

直到 Vite 的出现,我才开始开始重视 Svelte。

从 Vite文档[3] 里可以看到它支持这些模板:

JavaScript TypeScript
vanilla[4] vanilla-ts[5]
vue[6] vue-ts[7]
react[8] react-ts[9]
preact[10] preact-ts[11]
lit[12] lit-ts[13]
lit-ts[13] svelte-ts[15]

能让祖师爷也重视的框架,不简单不简单~

我喜欢用 Demo 的方式学习新技术,Svelte 官方入门教程[16] 就提供了这种方式。

这是我觉得入门比较舒服且方便日后搜索的学习方式。

虽然 Svelte 官方入门教程[17] 已经给出很多例子,而且 Svelte中文网[18] 也有对应的翻译,但有些翻译看上去是机译,而且部分案例可能不太适合新手学习~

本文的目的是把 Svelte 的学习流程梳理出来,让第一次接触 Svelte 的工友能顺利上手。

**本文适合人群:有 HTMLCSSJS 基础,知道并已经安装了 Node**。

如果你是打算从0开始学习前端,那本文暂时还不适合你阅读。

Svelte 简介

Svelte[19] 是一个构建 web 应用程序的工具。

传统框架如 React 和 Vue 在浏览器中需要做大量的工作,而 Svelte 将这些工作放到构建应用程序的编译阶段来处理。

需要注意,Svelte 是一款编译器。它可以将按照规定语法编写的代码打包成浏览器能运行的项目。

和其他前端框架一样,同样也是使用 HTMLCSSJavaScript 进行开发。

作者

在学习 Svelte 之前先了解一下它的父亲(作者)。

Svelte 的作者叫 Rich Harris[20] ,正在吃东西的这位就是他。

01.jpg

可能国内大多数工友对他不是很熟悉(我也完全不熟),但应该听过 Rollup[21] 。

没错,他也是 Rollup[22] 的爸爸。

他在开发 Svelte 之前还开发过 Ractive.js[23] ,听说 Vue 的部分实现也是受到了 Ractive 的启发。

关于 Rich Harris 的介绍还有很多,我搜到的资料上这样介绍到:

  • 大学专业是学哲学的
  • 在纽约时报调查组工作的图形编辑,身兼记者和开发者职位

还有更多关于他和 Svelte 的介绍,可以看看 《Svelte \- The magical disappearing UI framework \- Interview with Rich Harris》[24]

Svelte 的优势

Svelte 翻译成中文就是“苗条”的意思,侧面表明它打包出来的包非常小。

Svelte 主要优势有以下几点。

1. 编译器

在打开Svelte官网[25]时就能看到这样的介绍。

Svelte 是一种全新的构建用户界面的方法。传统框架如 React 和 Vue 在浏览器中需要做大量的工作,而 Svelte 将这些工作放到构建应用程序的编译阶段来处理。

Svelte 组件需要在 .svelte 后缀的文件中编写,Svelte 会将编写好的代码翻编译 JSCSS 代码。

2. 打包体积更小

Svelte 在打包会将引用到的代码打包起来,而没引用过的代码将会被过滤掉,打包时不会加入进来。

在 《A RealWorld Comparison of Front-End Frameworks with Benchmarks \(2019 update\)》[26] 报告中,对主流框架进行了对比。

02.png

在经过 gzip 压缩后生成的包大小,从报告中可以看出,Svelte 打包出来的体积甩开 Vue、React 和 Angular 几条街。

这是因为经过 Svelte 编译的代码,仅保留引用到的部分。

3. 不使用 Virtual DOM

Virtual DOM 就是 虚拟DOM,是用 JS 对象描述 DOM 节点的数据,由 React 团队推广出来的。

虚拟DOM 是前端的网红,因此也有很多开发者开始研究和搞辩论赛。

网上有一张图对比了 Svelte 和 React 在数据驱动视图的流程

03.png

其实主要对比了使用虚拟DOM和直接操作真实DOM的区别。

在 React 中实现数据驱动视图大概流程是这样的:

数据发生变化 -> 通过diff算法判断要更新哪些节点 -> 找到要更新的节点 -> 更新真实DOM
复制代码

Vue 的数据更新原理其实也差不多,只是实现方式和使用语法会有所不同。

diff算法 会根据数据更新前和更新后生成的虚拟DOM进行对比,只有两个版本的虚拟DOM存在差异时,才会更新对应的真实DOM。

使用虚拟DOM对比的方式会比直接对比真实DOM的效率高。

而且真实DOM身上挂载的属性和方法非常多,使用虚拟DOM的方式去描述DOM节点树会显得更轻便。

但这也意味着每次数据发生变化时都要先创建一个虚拟DOM,并使用 diff算法 将新虚拟DOM与旧虚拟DOM进行比对,这个步骤会消耗一点性能和需要一点执行时间。

而 Svelte 在未使用虚拟DOM的情况下实现了响应式设计。

我以粗暴的方式理解:Svelte 会监听顶层组件所有变量,一旦某个变量发生变化,就更新使用过该变量的组件。这就仅仅只需更新受影响的那部分DOM元素,而不需要整个组件更新。

综上所述,在我的理解力,虚拟DOM的思想很优秀,也是顺应时代的产物,但虚拟DOM并不是最快的,JS 直接操作 DOM 才是最快。

《Virtual DOM is pure overhead》[27] 是 Svelte 官网上的一篇博客,专门讨论虚拟DOM。有兴趣的工友可以看看~

4. 更自然的响应式

这也是我刚接触 Svelte 时立刻喜欢上的理由。

这里说的响应式设计是只关于数据的响应,而不是像 Bootstrap 的响应式布局。

现在流行的前端框架基本都使用 数据驱动视图 这个概念,像 Vue 和 React 这些框架,都有响应式数据的概念。

但 Vue 和 React 在数据响应方面还是有点“不那么自然”,我简单举几个例子:

  • 在 React 中,如果需要更新数据并在视图中响应,需要使用 setState 方法更新数据。
  • 在 Vue2 中,响应式数据要放在 data 里,在 methods 中使用 this.xxx 来更新数据。
  • 在 Vue3 的 Composition API 语法中,需要使用 ref 或者 reactive 等方法包裹数据,使用 xxx.value 等方式修改数据。

上面这几种情况,感觉多少都添加了点东西才能实现响应式数据功能(至少在普通开发者开发时是这样)。

在 Svelte 的理念中,响应式应该给开发者一种无感体验,比如在 Excel 中,当我规定 C1 单元格的值是 A1 + B1 的和,设置好规则后,用户只需要修改 A1 和 B1 即可,C1 会自动响应,而不需再做其他操作。

04.gif

在这方面,Svelte 我认为在现阶段是做得最自然的。

05.gif

<h1>{name}</h1>

<script>
  let name = '雷猴'

  setTimeout(() => {
    name = '鲨鱼辣椒'
  }, 1000)
</script>
复制代码

上面的代码中,1秒后修改 name 的值,并更新视图。

从代码就能看出,在使用 Svelte 开发项目时,开发者一般无需使用额外的方法就能做到和 Vue、React 的响应式效果。

如果你对 Svelte 响应式原理感兴趣,推荐阅读 FESKY[28] 的 《Svelte 响应式原理剖析 —— 重新思考 Reactivity》[29]

也可以看看 《Rethinking reactivity》[30],看看官方对 reactivity 的思考。

5. 性能强

Stefan Krause 给出一份 性能测试报告(点击可查看)[31] 对比里多个热门框架的性能。从 Svelte 的性能测试结果可以看出,Svelte 是相当优秀的。

6. 内存优化

性能测试报告(点击可查看)[32] 也列出不同框架的内存占用程度,Svelte 对内存的管理做到非常极致,占用的内存也是非常小,这对于配置不高的设备来说是件好事。

第5和6点,由于测试报告比较长,我没截图放进文中。大家有兴趣可以点开链接查看测试报告[33]。

7. 更关注无障碍体验

在使用 Svelte 开发时会 自动对无障碍访问方面的体验进行检测,比如 img 元素没有添加 alt 属性,Svelte 会向你发出一条警告。无障碍体验对特殊人事来说是很有帮助的,比如当你在 img 标签中设置好 alt 属性值,使用有声浏览器会把 alt 的内容读出来。

在此我还要推荐2本关于设计体验的书。

  • 《点石成金:访客至上的Web和移动可用性设计秘笈》
  • 《包容性Web设计》

它们的封面长分别这个样子

06.jpg

07.jpg

Svelte 的优势肯定还有很多,但由于我开发经验不足,只能总结出以上这些了。如果你对 Svelte 有更多理解,欢迎在评论区补充~

Svelte 的不足

  1. Svelte 对 IE 是非常不友好的,但我并不把这放在眼里。如果想兼容 IE 我还是推荐使用 jQuery。
  2. Svelte 的生态不够丰富。由于是“新宠”,生态方面肯定是不如 Vue 和 React 的。

与 Svelte 相关的库

Sapper

Sapper 官网地址[34]

Sapper 是构建在 Svelte 上的框架,Sapper 提供了页面路由、布局模板、SSR等功能。

Svelte Native

Svelte Native 官网地址[35]

Svelte Native 是建立在 NativeScript[36] 之上的产物,可以开发安卓和iOS应用,是一个跨端技术。

有点类似于 React Native 和 Weex 之类的东西。

svelte-gl

svelte-gl 仓库[37]

svelte-gl 还没正式发布,但这是个很有趣的工具,它和 three.js[38] 类似,专门做 3D应用的。

虽然现在 github 上的 Star 还不是很多,但也可以写些 demo 玩玩。

创建项目

在开始之前,你需要在电脑上安装 Node[39] 环境。

编辑工具我使用了 VS Code ,同时安装了 Svelte for VS Code 扩展插件[40] 。

使用 Svelte 前,必须有一个开发环境。

创建或使用开发环境有以下几种方式:

  1. REPL
  2. Rollup
  3. Webpack
  4. Parcel
  5. Vite

本文使用的是 Vite 创建项目,但上面列出的所有方式我都会逐一说说。

REPL

REPL 是 Svelte 提供的一个线上环境,打开 Svelte 官网[41] 可以看到顶部导航栏上面有个 REPL[42] 的选项。点击该选项就可以跳转到 Svelte 线上开发环境了。

08.png

09.png

REPLread(读取)evaluate(执行)print(打印)loop(循环) 这几个单词的缩写。

如果你只是想尝试 Svelte 的某些功能或者测试小型代码,可以使用这款线上工具。

REPL 还提供了多组件开发,按左上角的 +号 可以创建新组件。组件的内容稍后会说到。

界面右侧,顶部有3个选项:

  • Result: 运行结果。
  • JS output: Svelte 编译后的 JS 代码。
  • CSS output: Svelte 编译后的 CSS 代码。

10.png

REPL 界面右上角还有一个下载按钮。

11.png

当你在线上环境写好代码,可以点击下载按钮把项目保存到本地,下载的文件是一个 zip,需要自己手动解压。

然后使用以下命令初始化项目并运行即可。

# 1、初始化项目
npm install

# 2、运行项目
npm run dev

# 3、在浏览器访问 http://localhost:5000
复制代码

运行结果:

12.png

Rollup 版

Svelte 官方也提供了一个命令,可以下载 Svelte 项目到本地。

命令最后需要输入你的项目名称。

# 1、下载模板
npx degit sveltejs/template 项目名称

# 2、安装依赖
npm install

# 3、运行项目
npm run dev

# 4、在浏览器访问 http://localhost:8080
复制代码

运行结果:

13.png

这是官方提供的创建项目方式,这个项目是使用 Rollup 打包的。

Rollup 和 Svelte 都是同一个作者(Rich Harris[43] )开发的,用回自家东西很正常。

Webpack 版

如果你不想使用 Rollup 打包项目,可以尝试使用 Webpack。

# 1、下载模板
npx degit sveltejs/template-webpack 项目名称

# 2、安装依赖
npm install

# 3、运行项目
npm run dev

# 4、在浏览器访问 http://localhost:8080/
复制代码

运行结果:

14.png

Parcel 版

我并 不推荐使用 该方法创建项目,因为 Svelte 并没有提供使用 Parcel 打包工具的模板。但 GitHub 上有第三方的解决方案(点击访问仓库)[44]。

将 DeMoorJasper/parcel-plugin-svelte[45] 的代码下载下来。

# 1、进入 `packages/svelte-3-example` 目录

# 2、安装依赖
npm install

# 3、运行项目
npm run start

# 4、在浏览器访问 http://localhost:1234/
复制代码

运行结果:

15.png

Vite 版

本文接下来所有例子都是使用 Vite 创建 Svelte 项目进行开发的。

使用 Vite 创建项目的原因是:快!

# 1、下载模板的命令
npm init vite@latest

# 2、输入项目名

# 3、选择 Svelte 模板(我没选ts)

# 4、进入项目并安装依赖
npm install

# 5、运行项目
npm run dev

# 6、在浏览器访问 http://127.0.0.1:5173/
复制代码

运行结果:

16.png

本文使用 Vite 创建项目,目录结构和 Rollup版 创建出来的项目结构稍微有点不同,但开发逻辑是一样的。

起步

index.htmlsrc/main.jssrc/App.svelte 这三个是最主要的文件。

index.html 是项目运行的入口文件,它里面引用了 src/main.js 文件。

src/main.js 里引入了 src/App.svelte 组件,并使用以下代码将 src/App.svelte 的内容渲染到 #app 元素里。

const app = new App({
  target: document.getElementById('app')
})
复制代码

target 指明目标元素。

我们大部分代码都是写在 .svelte 后缀的文件里。

.svelte 文件主要保安 多个 HTML 元素1个 script 元素1个 style 元素 。这3类元素都是可选的。

我们主要的工作目录是 src 目录。

为了减轻学习难度,我们先做这几步操作。

1、清空全局样式

如果你使用 Rollup版 创建项目,不需要做这一步。

在使用 Vite 创建的 Svelte 项目中,找到 src/app.css 文件,并把里面的内容清空掉。

2、改造 src/App.svelte

src/App.svelte 文件改成以下内容

<script>
  let name = '雷猴'

  function handleClick() {
    name = '鲨鱼辣椒'
  }
</script>

<div>Hello {name}</div>
<button on:click={handleClick}>改名</button>
复制代码

此时点击按钮,页面上的 “雷猴” 就会变成 “鲨鱼辣椒”

17.gif

上面的代码其实和 Vue 有点像。

  • 变量和方法都写在 <script> 标签里。
  • HTML 中使用 {} 可以绑定变量和方法。
  • 通过 on:click 可以绑定点击事件。

只需写以上代码,Svelte 就会自动帮我们做数据响应的操作。一旦数据发生改变,视图也会自动改变。

是不是非常简单!

基础模板语法

Svelte 的模板语法其实和 Vue 是有点像的。如果你之前已经使用过 Vue,那本节学起来就非常简单。

插值

在 “起步章节” 已经使用过 插值 了。在 Svelte 中,使用 {} 大括号将 script 里的数据绑定到 HTML 中。

18.png

<script>
  let name = '雷猴'
</script>

<div>{name}</div>
复制代码

此时页面上就会出现 name 的值。

这种语法和 Vue 是有点像的,Vue 使用双大括号的方式 {{}} 绑定数据。Svelte 就少一对括号。

表达式

HTML 中除了可以绑定变量外,还可以绑定表达式。

19.png

<script>
  let name = '雷猴'

  function sayHi() {
    return `${name} 世界!`
  }

  let a = 1
  let b = 2

  let state = false
</script>

<div>{sayHi()}</div>

<div>{a} + {b} = {a + b}</div>

<div>{state ? '雷猴' : '鲨鱼辣椒'}</div>
复制代码

属性绑定

HTML 的属性需要动态绑定数据时,也是使用 {} 语法。

20.png

<script>
  let name = '雷猴'
</script>

<div title={name}>Hello</div>
复制代码

当鼠标放到 div 标签上时,会出现 title 里的提示信息。

渲染 HTML 标签 @html

如果只是使用插值的方法渲染带有 HTML 标签的内容,Svelte 会自动转义 <> 之类的标签。

21.png

<script>
  let h1El = '<h1 style="color: pink;">雷猴</h1>'
</script>

<div>{h1El}</div>
复制代码

这种情况多数出现在渲染富文本。

在 Vue 中有 v-html 方法,它可以将 HTML 标签渲染出来。在 Svelte 中也有这个方法,在插值前面使用 @html 标记一下即可。

22.png

<script>
  let h1El = '<h1 style="color: pink;">雷猴</h1>'
</script>

<div>{@html h1El}</div>
复制代码

但此方法有可能遭受 XSS 攻击。

我在 《NodeJS 防止xss攻击》[46] 中简单演示过 XSS 攻击,有兴趣的可以看看。

样式绑定

在日常开发中,给 HTML 标签设置样式主要通过 行内 styleclass 属性。

基础的 HTML 写法和原生的一样,这里不过多讲解。

下面主要讲动态设置样式,也就是将 JS 里的变量或者表达式绑定到 style 或者 class 里。

行内样式 style

23.gif

<script>
  let color = 'red'

  setTimeout(() => {
    color = 'blue'
  }, 1000)
</script>

<div style="color: {color}">雷猴</div>
复制代码

1秒后,文字从红色变成蓝色。

绑定 class

24.gif

<script>
  let foo = true

  setTimeout(() => {
    foo = false
  }, 1000)
</script>

<div class:active={foo}>雷猴</div>

<style>
  .active {
    color: red;
  }
</style>
复制代码

HTML 里可以使用 class:xxx 动态设置要激活的类。这里的 xxx 是对应的类名。

语法是 class:xxx={state} ,当 statetrue 时,这个样式就会被激活使用。

条件渲染 #if

使用 {#if} 开头,{/if} 结尾。

基础条件判断

{#if 条件判断}
...
{/if}
复制代码

举个例子

25.gif

<script>
  let state = true

  setTimeout(() => {
    state = false
  }, 1000)
</script>

{#if state}
  <div>雷猴</div>
{/if}
复制代码

1秒后改变状态

两种条件

{#if 条件判断}
...
{:else}
...
{/if}
复制代码

举个例子

26.gif

<script>
  let state = true

  setTimeout(() => {
    state = false
  }, 1000)
</script>

{#if state}
  <div>雷猴</div>
{:else}
  <div>鲨鱼辣椒</div>
{/if}
复制代码

多种条件

{#if 条件判断}
...
{:else if 条件判断}
...
{/if}
复制代码

举个例子

27.gif

<script>
  let count = 1

  setInterval(() => {
    count++
  }, 1000)
</script>

{#if count === 1}
  <div>雷猴</div>
{:else if count === 2}
  <div>鲨鱼辣椒</div>
{:else}
  <div>蟑螂恶霸</div>
{/if}
复制代码

条件渲染的用法比较简单,只要 JS 基础就能看得懂。

列表渲染 #each

如果你有一堆数据需要展示出来,可以使用 #each 方法。

使用 {#each} 开头,{/each} 结尾。

遍历数组

{#each expression as name}
...
{/each}
复制代码

举个例子

28.png

<script>
  let list = ['a', 'b', 'c', 'd', 'e', 'f']
</script>

<ul>
  {#each list as item}
   <li>{item}</li>
  {/each}
</ul>
复制代码

要注意,Svelte 和 Vue 的遍历在写法上有点不同。

Vue的方式是:

<div v-for="元素 in 源数据">
  <span>{{元素}}</span>
</div>
复制代码

Svelte的方式是:

<div>
  {#each 源数据 as 元素}
    <span>{元素}</span>
  {/each}
</div>
复制代码

遍历数组(带下标)

29.png

<script>
  let list = ['a', 'b', 'c', 'd', 'e', 'f']
</script>

<ul>
  {#each list as item, index}
   <li>{index} -- {item}</li>
  {/each}
</ul>
复制代码

注意:as 后面首先跟着元素,然后才是下标。而且元素和下标不需要用括号括起来。

如果元素是对象,可以解构

30.png

<script>
  let list = [
    {name: '雷猴'},
    {name: '鲨鱼辣椒'}
  ]
</script>

<ul>
  {#each list as {name}}
   <li>{name}</li>
  {/each}
</ul>
复制代码

默认内容

如果源数据没有内容,是空数组的情况下,还可以组合 {:else} 一起使用。

31.png

<script>
  let list = []
</script>

<div>
  {#each list as {name}}
   <div>{name}</div>
  {:else}
   <div>暂无数据</div>
  {/each}
</div>
复制代码

事件绑定 on:event

使用 on: 指令监听 DOM 事件,on: 后面跟随事件类型

语法:

on:事件类型={事件名}
复制代码

举个例子,点击按钮时在控制台输出 “雷猴”。

32.gif

<script>
  function sayHi() {
    console.log('雷猴')
  }
</script>

<button on:click={sayHi}>打招呼</button>
复制代码

绑定其他事件(比如change等)也是同样的道理。

事件修饰符

如果你只希望某些事件只执行一次,或者取消默认行为,或者阻止冒泡等,可以使用事件修饰符。

语法:

on:事件类型|修饰符={事件名}
复制代码

举个例子,我希望点击事件只能执行一次,之后再点击都无效,可以使用官方提供的 once 修饰符。

33.gif

<script>
  function sayHi() {
    console.log('雷猴')
  }
</script>

<button on:click|once={sayHi}>打招呼</button>
复制代码

从上图可以看出,多次点击都只是输出1次“雷猴”。

除了 once 之外,还有以下这些修饰符可以用:

  • preventDefault :禁止默认事件。在程序运行之前调用 event.preventDefault()
  • stopPropagation :调用 event.stopPropagation(), 防止事件到达下一个标签
  • passive :改善了 touch/wheel 事件的滚动表现(Svelte会在合适的地方自动加上它)
  • capture:表示在 _capture_阶段而不是_bubbling_触发其程序
  • once :程序运行一次后删除自身

串联修饰符

修饰符还可以串联起来使用,比如 on:click|once|capture={...}

但需要注意,有些特殊的标签使用修饰符会出现“意想不到”的结果,比如 <a> 标签。

34.gif

<script>
  function toLearn() {
    console.log('还在思考要不要学Canvas')
  }
</script>

<a
  href="https://juejin.cn/post/7116784455561248775"
  on:click|once|preventDefault={toLearn}
>去学习Canvas ?</a>
复制代码

本来是想给 <a> 标签绑定一个点击事件,第一次点击时在控制台输出一句话,并且禁止 <a> 标签的默认事件。

所以使用了 oncepreventDefault 修饰符。

但实际上并非如此。上面的代码意思是 once 设定了只执行一次 toLearn 事件,并且只有一次 preventDefault 是有效的。

只有点击时就不触发 toLearn 了,而且 preventDefault 也会失效。所以再次点击时,<a> 元素就会触发自身的跳转功能。

数据绑定 bind

数据绑定通常会和表单元素结合使用。

bind 可以做到双向数据绑定的效果。我觉得 Svelte 里的 bind 有点像 Vue 的 v-model

语法:

bind:property={variable}
复制代码

input 单行输入框

35.gif

<script>
  let msg = 'hello'

  function print() {
    console.log(msg)
  }
</script>

<input type="text" value={msg} />
<button on:click={print}>打印</button>
复制代码

如果只是使用 value={msg} 的写法,input 默认值是 hello ,当输入框的值发生改变时,并没有把内容反应回 msg 变量里。

此时就需要使用 bind 了。

36.gif

<!-- 省略部分代码 -->
<input type="text" bind:value={msg} />
复制代码

textarea 多行文本框

多行文本框同样绑定在 value 属性上。

37.gif

<script>
  let msg = 'hello'
</script>

<textarea type="text" bind:value={msg} />
<p>{msg}</p>
复制代码

input range 范围选择

因为都是 input 元素,只是 type 不同而已。所以范围选择元素同样需要绑定 value

38.gif

<script>
  let val = 3
</script>

<input type="range" bind:value={val} min=0 max=10 />
<p>{val}</p>
复制代码

radio 单选

单选框通常是成组出现的,所以要绑定一个特殊的值 bind:grout={variable}

39.gif

<script>
  let selected = '2'
</script>

<input type="radio" bind:group={selected} value="1" />
<input type="radio" bind:group={selected} value="2" />
<input type="radio" bind:group={selected} value="3" />
<p>{selected}</p>
复制代码

checkbox 复选框

40.gif

<script>
  let roles = []
</script>

<input type="checkbox" bind:group={roles} value="雷猴" />
<input type="checkbox" bind:group={roles} value="鲨鱼辣椒" />
<input type="checkbox" bind:group={roles} value="蟑螂恶霸" />
<input type="checkbox" bind:group={roles} value="蝎子莱莱" />

<p>{roles}</p>
复制代码

select 选择器

41.gif

<script>
  let selected = 'a'
</script>

<select bind:value={selected}>
 <option value='a'>a</option>
 <option value='b'>b</option>
 <option value='c'>c</option>
</select>

<span>{selected}</span>
复制代码

select multiple 选择器

multiplecheckbox 有点像。

42.gif

<script>
  let selected = []
</script>

<select multiple bind:value={selected}>
 <option value="雷猴">雷猴</option>
 <option value="鲨鱼辣椒">鲨鱼辣椒</option>
 <option value="蟑螂恶霸">蟑螂恶霸</option>
 <option value="蝎子莱莱">蝎子莱莱</option>
</select>

<span>{selected}</span>
复制代码

简写形式

如果 bind 绑定的属性和在 JS 里声明的变量名相同,那可以直接绑定

43.gif

<script>
  let value = 'hello'
</script>

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

<p>{value}</p>
复制代码

这个例子中,bind:value 绑定的属性是 value ,而在 JS 中声明的变量名也叫 value ,此时就可以使用简写的方式。

$: 声明反应性

通过使用$: JS label 语法[47]作为前缀。可以让任何位于 top-level 的语句(即不在块或函数内部)具有反应性。每当它们依赖的值发生更改时,它们都会在 component 更新之前立即运行。

上面这段解释是官方文档的解释。

$: 在文档中称为 Reactivity ,中文文档成它为 反应性能力

但我使用 $: 时,觉得这个功能有点像 Vue 的 computed

$: 可以监听表达式内部的变化从而做出响应。

44.gif

<script>
  let count = 0;
  $: doubled = count * 2;

  function handleClick() {
    count += 1;
  }
</script>

<button on:click={handleClick}>
  点击加1
</button>

<p>{count} 翻倍后 {doubled}</p>
复制代码

使用 $: 声明的 double 会自动根据 count 的值改变而改变。

如果将以上代码中 $: 改成 let 或者 var 声明 count ,那么 count 将失去响应性。

这样看来,真的和 Vue 的 computed 的作用有那么一点像。

异步渲染 #await

Svelte 提供异步渲染标签,可以提升用户体验。

语法:

{#await expression}
...
{:then name}
...
{:catch name}
...
{/await}
复制代码

#await 开始,以 /await 结束。

:then 代表成功结果,:catch 代表失败结果。

expression 是判断体,要求返回一个 Promise

其实用法和 #if ... :else if ... /if 有那么一丢丢像。

举个例子

45.gif

<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}
复制代码

如果将上面的 resolve 改成 reject 就会走 :catch 分支。

基础组件

在 Svelte 中,创建组件只需要创建一个 .svelte 为后缀的文件即可。

通过 import 引入子组件。

比如,在 src 目录下有 App.sveltePhone.svelte 两个组件。

App.svelte 是父级,想要引入 Phone.svelte 并在 HTML 中使用。

46.png

App.svelte

<script>
  import Phone from './Phone.svelte'
</script>

<div>子组件 Phone 的内容:</div>
<Phone />
复制代码

Phone.svelte

<div>电话:13266668888</div>
复制代码

组件通讯

组件通讯主要是 父子组件 之间的数据来往。

父传子

比如上面的例子,手机号希望从 App.svelte 组件往 Phone.svelte 里传。

可以在 Phone.svelte 中声明一个变量,并公开该变量。

App.svelte 就可以使用对应的属性把值传入。

47.png

App.svelte

<script>
  import Phone from './Phone.svelte'
</script>

<div>子组件 Phone 的内容:</div>
<Phone number="88888888" />
复制代码

Phone.svelte

<script>
  export let number = '13266668888'
</script>

<div>电话:{number}</div>
复制代码

如果此时 App.svelte 组件没有传值进来,Phone.svelte 就会使用默认值。

子传父

如果想在子组件中修改父组件的内容,需要把修改的方法定义在父组件中,并把该方法传给子组件调用。

同时需要在子组件中引入 createEventDispatcher 方法。

48.gif

App.svelte

<script>
  import Phone from './Phone.svelte'
  function print(data) {
    console.log(`手机号: ${data.detail}`)
  }
</script>

<div>子组件 Phone 的内容:</div>
<Phone on:printPhone={print} />
复制代码

Phone.svelte

<script>
  import { createEventDispatcher } from 'svelte'
  const dispatch = createEventDispatcher()

  function printPhone() {
    dispatch('printPhone', '13288888888')
  }
</script>

<button on:click={printPhone}>输出手机号</button>
复制代码

父组件接受参数是一个对象,子组件传过来的值都会放在 detail 属性里。

插槽 slot

和 Vue 一样,Svelte 也有组件插槽。

在子组件中使用 <slot> 标签,可以接收父组件传进来的 HTML 内容。

49.png

App.svelte

<script>
  import Phone from './Phone.svelte'
</script>

<div>子组件 Phone 的内容:</div>
<Phone>
  <div>电话:</div>
  <div>13288889999</div>
</Phone>
复制代码

Phone.svelte

<style>
 .box {
  width: 100px;
  border: 1px solid #aaa;
  border-radius: 8px;
  box-shadow: 2px 2px 8px rgba(0,0,0,0.1);
  padding: 1em;
  margin: 1em 0;
 }
</style>

<div class="box">
 <slot>默认值</slot>
</div>
复制代码

生命周期

生命周期是指项目运行时,指定时期会自动执行的方法。

Svelte 中主要有以下几个生命周期:

  • onMount: 组件挂载时调用。
  • onDestroy: 组件销毁时执行。
  • beforeUpdate: 在数据更新前执行。
  • afterUpdate: 在数据更新完成后执行。
  • tick: DOM元素更新完成后执行。

以上生命周期都是需要从 svelte 里引入的。

onMount 举个例子

50.gif

<script>
  import { onMount } from 'svelte'
  let title = 'Hello world'

  onMount(() => {
    console.log('onMount')
    setTimeout(() => title = '雷猴', 1000)
  })
</script>

<h1>{title}</h1>
复制代码

在组件加载完1秒后,改变 title 的值。

onDestroybeforeUpdateafterUpdate 都和 onMount 的用法差不多,只是执行的时间条件不同。你可以自己创建个项目试试看。

tick 是比较特殊的,tick 和 Vue 的 nextTick 差不多。

在 Svelte 中,tick 的使用语法如下:

import { tick } from 'svelte'

await tick()
// 其他操作
复制代码

总结

本文主要讲解了 Svelte 的基础用法,但 Svelte 的内容和 API 远不止此。它还有很多高级的用法以及提供了过渡动画功能等,这些都会放在高级篇讲解。

Svelte 是一个 Web 应用的构建工具,它打包出来的项目体积比较小,性能强,不使用虚拟DOM。

Svelte 的兼容性和周边生态相比起 VueReact 会差一点。

所以日常项目中需要根据 Svelte 的优缺点进行取舍。

本文由哈喽比特于1年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/TR-IkoyDcann9BdsgqHe9Q

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:8月以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:8月以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:8月以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:8月以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:8月以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:8月以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:8月以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:8月以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:8月以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:8月以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:8月以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:8月以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:8月以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:8月以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:8月以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:8月以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:8月以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:8月以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:8月以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:8月以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  236889次阅读
vscode超好用的代码书签插件Bookmarks 1年以前  |  6994次阅读
 目录