前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >前端Svelte框架初体验

前端Svelte框架初体验

作者头像
xiangzhihong
发布2022-07-30 10:48:14
3.8K1
发布2022-07-30 10:48:14
举报
文章被收录于专栏:向治洪向治洪

最近这些年,随着React、Vue、Angular三大框架逐渐稳定,前端技术栈的迭代似乎也渐渐缓慢下来。并且随着React 16版本推出 Fiber, Vue 3.0 版本的正式发布,前端三大框架都有了自己的护城河。

不过话说回来,十年前我们谁会想到前端也会自成一派,变得如此智能。试想一下,如果我们把目光拉伸到未来十年,前端行业会出现怎么样的发展呢,会不会有挑战React或者Vue的新技术出现呢? 对于未来的发展,或许我们无从知晓,但是我们今天给大家推荐的Svelte 或许会是一个不错的挑战者。

在这里插入图片描述
在这里插入图片描述

一、Svelte简介

Svelte是一个新兴的热门前端框架,作者是 Rich Harris,被称为前端界的【轮子哥】,有Ractive、Rollup 和 Buble开源作品。

在这里插入图片描述
在这里插入图片描述

在官方的介绍中,Svelte 即是一个前端 UI框架,同时也是一个 编译器。在《State of JS survey of 2020》报告中,它被预测为未来十年可能取代React和Vue等其他框架的新兴技术。在开源托管网站Github上,Svelte也获得了超过61k的关注,这仅次于明星框架React和Vue。

在这里插入图片描述
在这里插入图片描述

在最新的开发者感兴趣的前端框架中,Svelte更是超过传统的知名框架Vue和React,排在第一位。

在这里插入图片描述
在这里插入图片描述

不过,这倒并不是说Svelte有多厉害,因为Svelte 当前仍是一个小众的开发框架,市场占有率方面也仍小于React和Vue,不过进步是特别明显的。

在这里插入图片描述
在这里插入图片描述

二、Svelte的优点

事实上,作为一个前端框架,Svelte在语法、使用体验上没有什么特别之处。真正不同的地方,是Svelte对前端AOT(ahead-of-time,可以理解为预编译)的探索。

如果大家对React、Vue 的设计思路比较了解的话就会知道,他们必须引入运行时 (runtime) 代码,用于虚拟dom、diff 算法。而Svelte 的设计思路是【通过静态编译减少框架运行时的代码量,即预编译】,Svelted完全溶入JavaScript,应用所有需要的运行时代码都包含在bundle.js里面,因此不需要额外在引入运行时。

2.1 No Runtime

React 和 Vue 都是基于运行时的框架,当用户操作页面进行各种操作改变组件的状态时,框架的运行时会根据组件状态(state)计算(diff)出哪些DOM节点需要被更新,从而更新视图。这就意味着,基于运行时框架本身所依赖的代码也会被打包到最终的构建产物中,结果是不可避免增加了打包后的体积。下图是常见的前端框架运行时的大小。

在这里插入图片描述
在这里插入图片描述

可以看到,最小的Vue有58k、React则有97.5k。 所以,如果我们如果使用React开发一个小型组件,即使里面的逻辑代码很少,但是打包出来的bundle size也会超过100k。对于大型后台管理系统来说100k 不算什么,但是对于特别注重用户端加载性能的场景来说,一个组件已经足够大了。

下面是Jacek Schae大神使用市面上主流的框架编写同样的Realword 应用,然后最终打包发布的体积。

在这里插入图片描述
在这里插入图片描述

可以看到,Svelte的bundle包的大小是Vue的1/4,React的1/20,体积上的优势还是相当明显的。

2.2 Less-Code

并且,编写同样的组件时,和 Vue 、React相比,Svelte只需要更少的代码。比如,React 官方的加法的示例代码:

代码语言:javascript
复制
//React
const [count, setCount] = useState(0);
function increment() {
  setCount(count + 1);
}

而如果使用Svelte来实现的话,代码量明显变少。这是因为Svelte可以直接使用赋值操作符更新组件的状态。

代码语言:javascript
复制
//Svelte
let count = 0;
function increment() {
  count += 1;
}

如果说上面的例子太简单了,不足以看出效果。那么下面还是使用Jacek Schae 编写Realword 应用代码行数的统计来说明。

在这里插入图片描述
在这里插入图片描述

2.3 Hight-Performance

在Virtual Dom已经是前端框架标配的今天, Svelte 声称自己是没有使用Virtual Dom, 那他是怎么还能保证高性能的呢?

下面是Jacek Schae 在《A RealWorld Comparison of Front-End Frameworks with Benchmarks》一文中使用主流的前端框架来编写 RealWorld 应用,使用 Chrome 的Lighthouse Audit测试性能,得出数据是Svelte 略逊于Vue,但好于 React。

在这里插入图片描述
在这里插入图片描述

而使用 JavaScript Framework Benchmark工具来分析各个框架的执行时间、内存占用及启用时间也给出了同样的答案。

在这里插入图片描述
在这里插入图片描述

在执行速度的方面,经过多次测试,Svelte 速度最快,Vue 紧随其后,React 和 Angular 速度较慢。

在这里插入图片描述
在这里插入图片描述

而在内存占用方面,Svelte 仍然保持大幅度领先,Vue 略微优于并驾齐驱的 React 和 Angular。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7afO7KwT-1658977170654)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5bcda28987a04c008e556fbdc654ef33~tplv-k3u1fbpfcp-watermark.image?)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7afO7KwT-1658977170654)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5bcda28987a04c008e556fbdc654ef33~tplv-k3u1fbpfcp-watermark.image?)]

在启动方面,Svelte 的启动速度也非常出色,Vue 略逊一筹,React 和 Angular 紧随其后。 可以看到,在性能方面,Svelte并不逊色其他框架。

三、Svelte的缺点

当然,作为一个尚处在起步阶段的框架,Svelte 还有很多的不足,如果是在大型的商业项目中中使用 , 需要特别的谨慎。例如,下面是不同策略对代码生成量的影响。

在这里插入图片描述
在这里插入图片描述

根据尤大的测试,Svelte 是通过生成命令式的一个一个节点,然后把节点拼接这些 Javascript 代码。那这个策略就导致同等的这个组件源码之下 Svelte 每个组件的编译输出会更臃肿。虽然大家会第一印象是觉得说 Svelte 是以轻量而出名的,但其实我们会发现,在相对大型的项目中,在项目中组件超过 15 个之后,Svelte 的整体的打包体积优势就已经几乎已不存在。

除此之外,Svelte的缺点还包括:没有像AntD那样成熟的UI库。不支持预处理器,比如说less/scss,需要自己单独的配置 webpack loader等。不过,可以看到,Svelte正在快速的更新,最新版本解决的问题也不少。

在这里插入图片描述
在这里插入图片描述

四、快速上手

4.1 创建项目

和其他前端框架一样,创建一个Svelte项目是非常简单的,命令如下。

代码语言:javascript
复制
npm create svelte@latest my-app
cd my-app
npm install
npm run dev

然后在浏览器中打开 http://localhost:5173/ 就能访问对应的页面,运行的效果如下图。

在这里插入图片描述
在这里插入图片描述

如果需要修改端口号,可以打开package.json 文件,然后在启动命令里修改环境变量 PORT。

代码语言:javascript
复制
"scripts": {
  "dev": "PORT=4000 rollup -c -w",
},

4.2 less配置

创建Svelte项目的时候,模板本身是不携带任何插件的,如果需要在 Svelte 组件中写 less,需要安装相关的依赖。

代码语言:javascript
复制
npm install svelte-preprocess-less less

然后,在 rollup.config.js 中添加相关的配置,如果没有 rollup.config.js 文件,可以新建一个。

代码语言:javascript
复制
import sveltePreprocess from 'svelte-preprocess';
import { less as svelteLess } from 'svelte-preprocess-less';
export default {
   plugins: [
      svelte({
         preprocess: sveltePreprocess({
            style: svelteLess(),
         }),
      }),
   ],
};

接下来,我们就可以在组件中的

代码语言:javascript
复制
 <style lang="less"> 
  ...
 </style>

五、语法基础

5.1 基本用法

在Svelte应用中,一个.svelte就是一个组件,它由html、css和js代码组成,类似vue的写法。其中,

代码语言:javascript
复制
<script>
    let src = 'image.gif';
    let name = 'Rick Astley';
</script>
<img {src} alt="{name} dances.">

当属性名和变量名是一样的时候,我们也可以简写省略掉变量名。而样式,和其他的写法是一样的。

代码语言:javascript
复制
<style>
   .counter {
   display: flex;
   border-top: 1px solid rgba(0, 0, 0, 0.1);
   border-bottom: 1px solid rgba(0, 0, 0, 0.1);
   margin: 1rem 0;
  }
</style>

不过,上面说的例子都是简单的一个小组件,对于一个完整的应用程序来说,必然是由多个组件构成的。和其他的框架一样,使用时需要import引入进来,不同之处在于,import需要写在

代码语言:javascript
复制
<script>
   import Counter from '$lib/Counter.svelte';
</script>
 
<section>
   <Counter />
</section>

5.2 响应式

响应式也是Svelte的核心特性之一,在js里直接修改绑定的变量,就可以同步看到DOM上数据的改变。

代码语言:javascript
复制
<script>
    let count = 0;
    function handleClick() {
        count++;
    }
</script>
<button on:click={handleClick}>
    Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

类似vue里的computed,这里叫【反应式声明】,这样写:

代码语言:javascript
复制
let count = 0;
$: doubled = count * 2;

然后,就可以在众像用count那样使用doubled。Svelet的响应式是有赋值语句触发的,所以像数组的push、splice这些操作就不会触发更新,正确的做法是需要手动添加一个看似多余的赋值语句,比如。

代码语言:javascript
复制
<script>
    let numbers = [1, 2, 3, 4];
    function addNumber() {
        numbers.push(numbers.length + 1);
        numbers = numbers;
        // 或者写成
        // numbers = [...numbers, numbers.length + 1];
    }
    $: sum = numbers.reduce((t, n) => t + n, 0);
</script>
<p>{numbers.join(' + ')} = {sum}</p>
<button on:click={addNumber}>
    Add a number
</button>

5.3 属性传值

在前端框架中,组件之间的传值一般使用的是构造函数。在Svelte中,组件之间的传值也比较简单,不过需要额外在子组件里,使用export关键字将值传递出去。

代码语言:javascript
复制
<Nested answer={21}/>


//子组件使用export导出
<script>
    export let answer;
</script>
<p>The answer is {answer}</p>

5.4 逻辑语句

和其他的框架不同,Svelte的逻辑语句需要在HTML里面处理,比如{#if xxxxx},语法方面感觉比不是很友好。

代码语言:javascript
复制
{#if user.loggedIn}
   <button on:click={toggle}>
       Log out
   </button>
{/if}

而对于if-else的写法,如下。

代码语言:javascript
复制
{#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}

其中,#表示一个块逻辑的开始,/表示结束,:表示继续。

如果要进行循环,一般使用的是for/each。不过,Svelte的循环语句实在让人难以接受。

代码语言:javascript
复制
<script>
    let cats = [
        { id: 'J_aiyznGQ', name: 'Keyboard Cat' },
        { id: 'z_AbfPXTKms', name: 'Maru' },
    ];
</script>
<h1>The Famous Cats of YouTube</h1>
<ul>
    {#each cats as cat,index}
        <li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
            {index+1} {cat.name}
        </a></li>
    {/each}
</ul>

5.5 事件

和其他框架一样,Svelte提供了on:click,on:mousemove等指令来监听事件。

代码语言:javascript
复制
<button on:click={() => (count += 1)} aria-label="Increase the counter by one">
   <svg aria-hidden="true" viewBox="0 0 1 1">
      <path d="M0,0.5 L1,0.5 M0.5,0 L0.5,1" />
   </svg>
</button>

当然,事件监听的时候也可以使用事件修饰符,用‘|’分隔,表示可以连续使用多个。

代码语言:javascript
复制
on:click|once|capture={handleEvent}

特别需要注意的一点是,如果子组件内部想要接受父组件的点击事件,只需要在子组件内部加上on:click即可。

代码语言:javascript
复制
//父组件
<script>
    import FancyButton from './FancyButton.svelte';
    function handleClick() {
        alert('clicked');
    }
</script>
<FancyButton on:click={handleClick}/>


//子组件
<button on:click>
    Click me
</button>

5.6 事件绑定

Svelte里的数据绑定和Vue、React时类似的,使用的是bind:value方式进行绑定。例如,下面是input标签的事件绑定。

代码语言:javascript
复制
<script>
    let name = 'world';
</script>
<input bind:value={name}>
<h1>Hello {name}!</h1>

上述是单个值的绑定,那么绑定多个值的时候,可以用bind:group将value放在一起。

代码语言:javascript
复制
<label>
   <input type=checkbox bind:group={flavours} value={flavour}>
</label>

并且,bind:this可以绑定任何标签或者组件,并且可以获得标签的引用,类似于React的ref。

代码语言:javascript
复制
<canvas
    bind:this={canvas}
    width={32}
    height={32}
></canvas>


 
onMount(() => {
  const ctx = canvas.getContext('2d');
  .....
}

组件的属性也可以绑定,比如在父组件引用子组件的属性。

代码语言:javascript
复制
<Keypad bind:value={pin} on:submit={handleSubmit}/>

不过,作为一款年轻的前端框架,很少能够看到一些互联网公司将 Svelte 应用于生产,究其原因,无外乎以下几点:

  • 对低端手机支持不太友好,特别是用shadow等高级特性。
  • 生态不是很完善,配套的安全、性能测试、自动化等工具不是很完善。
  • 全新的语法,需要一定的学习成本。

参考:

携程机票前端Svelte生产实践

Svelte3聊天室|svelte+svelteKit仿微信聊天实例|svelte.js开发App

基于Svelte3+SvelteKit+Sass仿微信Mac界面聊天实战项目

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-07-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Svelte简介
  • 二、Svelte的优点
    • 2.1 No Runtime
      • 2.2 Less-Code
        • 2.3 Hight-Performance
        • 三、Svelte的缺点
        • 四、快速上手
          • 4.1 创建项目
            • 4.2 less配置
            • 五、语法基础
              • 5.1 基本用法
                • 5.2 响应式
                  • 5.3 属性传值
                    • 5.4 逻辑语句
                      • 5.5 事件
                        • 5.6 事件绑定
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档