在 JavaScript
前端开发框架中,Svelte
算是一个新来的搅局者,在网上我们已经听到很多关于 Svelte
的哔哔。因此我决定试试这个家伙,顺便跟 React
做个简单的比较。
本文将展示 Svelte
和 React
在构建一个基础应用的差异,其中涉及到的内容包括:
还有很多其他方面的内容需要讨论,例如 按需渲染 和 生命周期 等其他炫酷的概念。限于篇幅,这篇文章还是聚焦在基础使用上吧。
在继续往下阅读之前,你应该准备好如下环境:
Svelte 和 React.js 两者都是基于组件的 JavaScript 框架,主要用于 Web 应用的开发。最主要的区别是 Svelte 没有使用虚拟 DOM。Svelte 在构建的时候就将代码编译成 Vanilla JS 代码,而 React 在运行时解释代码。
Svelte 文档写道:
Svelte 是一种全新的构建 Web 应用的方法。诸如 React 和 Vue 这类传统的框架,它们的大部分工作都在浏览器上执行,而 Svelte 在构建应用的过程做就了大量的工作。
Svelte 没有使用虚拟 DOM 技术,而是当应用状态发生变化时,通过代码如手术般的更新 DOM。
酷!但是这些底层的细节对我来说并不重要。我只想从开发人员的角度看看,在使用 Svelte 和 React 开发应用程序时,感觉好吗?有趣吗?直观吗?
开工!
在这篇文章中,我们将创建一个很小的 Web 应用,产品经理给这个应用确定了如下需求:
首先使用如下命令在你电脑上创建一个新的目录,暂且命名为 svelte-react:
mkdir svelte-react
cd svelte-react
接着分别创建 Svelte 和 React 的应用模板并运行。这里 Svelte 的初始步骤比 React 多了一步,此外 Svelte 默认端口是 5000 ,而 React 是 3000 。
打开终端窗口,运行如下命令:
npx degit sveltejs/template svelte-test
cd svelte-test
npm install
npm run dev
打开第二个终端窗口,进入刚建好的 svelte-react 目录,运行命令:
npx create-react-app react-test
cd svelte-react
npm start
你会发现 Svelte 的命令运行快得多,因为你不是真正在运行一个工具,而是克隆一个项目模板。
运行完上述命令后,你会注意到 Svelte 和 React 各自生成很多很多的文件,感兴趣的话,可以随便浏览看看这些生成的文件。
不管是 Svelte 和 React ,都是把组件源码放到 src 文件夹下,Svelte 项目主要是一些扩展名为 svelte 的文件,而 React 项目则是一些 .js 的文件。
两个项目都有一个 App 组件,分别是 App.svelte 和 App.js 。用你喜好的编辑器分别打开这两个文件,清空它们,我们从头开始。
和 React 组件不同的是,Svelte 的代码更像是以前我们在写 HTML、CSS 和 JavaScript 一样。
所有的 JavaScript 代码都位于 Svelte 文件顶部的 <script></script>
标签当中。
然后是 HTML 代码,你还可以在 <style></style>
标签中编写样式代码。有趣的是,组件中的样式代码只对当前组件有效。这意味着在组件中为
标签编写的样式不会影响到其他组件中的
元素。
接下来我们开始编写 App.svelte,首先删空文件内容,然后添加一个空的 <script>
标签:
<script>
</script>
我们将在这个标签中编写大部分组件代码。
在 React 项目中,打开 App.js 文件,清空所有内容,然后添加如下代码:
function App() {
}
export default App;
这几行代码创建并输出了一个最基础的函数式组件,名为 App() 。注意到这里还有另外一个不同之处就是 —— Svelte 无需输出组件。
前面我们介绍过这个应用包含三个组件:App, Heading和Button。不管是 Svelte 还是 React ,Heading 和 Button 组件都被引入到 App 中,这样就可以被当成 App 的子组件使用。我们将在后面继续编写这三个组件的代码,但现在你只需要知道,构建 App 组件时需要引入其他两个组件。
Svelte 需要在 <script>
使用 import 语句进行组件引入,编辑 App.svelte 文件添加两个 import 语句:
<script>
import Button from './Button.svelte';
import Heading from './Heading.svelte';
</script>
React 的 import 语句位于文件的顶部,置于所有的函数或者类定义之前。在 App.js 最顶部,App() 函数之前,添加如下代码:
import Heading from './Heading.js';
import Button from './Button.js';
import { useState } from 'react';
在这里,React 同时引入了 userState 钩子,因为 App 是一个有状态的组件。而 Svelte 不需要这个东西。
App 是一个有状态的组件,它有两个状态值分别是 color 和 count。
color 表示按钮的颜色,这个值作为一个属性传递给 Button 组件,并且它在每次点击按钮的时候改变。其初始值是 #000000,即为黑色。
count 代表按钮点击的次数,其初始值为 0。
在 Svelte 中,状态等同于变量赋值,在 import 语句下方,<script>
标签之前添加如下状态定义:
let count = 0;
let color = '#000000';
Svelte 同时提供了名为”反应式声明“ 的概念,用来重新计算状态值,你不一定必须用这个,但如果状态值依赖于其他可能更改的状态,这时候就很方便。
需要注意的是在 Svelte 中是通过状态变量的赋值来实现 DOM 更新的。如果状态包含数组或者对象,当对数组使用类似 .push() 方法并不会触发 DOM 更新。Svelte 提供了一个详细文档来介绍这个问题。
现在已经引入了 useState 钩子,所以只需要让它工作起来即可。
在 App.js 的 App() 函数中添加如下状态声明:
const [count, setCount] = useState(0);
const [color, setColor] = useState('#000000');
上述代码创建一个名为 count 的状态变量,其初始值为 0,以及一个用来更新值的函数名为 setCount()。同样的,React 创建了另一个状态变量 color 初始值为 #000000 以及名为 setColor() 的更新函数。从这点来看,Svelte 的状态初始化方法要简单易懂得多。
两个项目我们都是要创建一个由 <main>
元素构建的用户界面,该元素包含两个嵌套的组件 Heading 和 Button。
App 组件传递属性给两个子组件。Heading 组件接收 count 状态值,Button 组件接收 color 状态值,此外还有一个名为 handleClick() 的事件处理函数。
Svelte 使用它自己的模板语言来创建用户界面,而 React 使用 JSX 。Svelte 模板语言跟写 HTML 没什么两样。接下来只需在 <script>
标签结束后开始编写。
拷贝如下
部分代码到 App.svelte 文件中,形如:
<script>
...
</script>
<main>
<Heading count={count} />
<Button color={color} handleClick={handleClick} />
</main>
回到 App.js, 将如下代码拷贝到你的 App() 函数中状态声明部分的下方:
return (
<main>
<Heading count={count} />
<Button color={color} handleClick={handleClick} />
</main>
)
该代码从 App() 函数中返回 UI 界面的 JSX。
这里 Svelte 和 React 的做法都很类似,属性的传递也几乎相同。而 Svelte 的模板看起来跟 React 的 JSX 很像。
如果你是一个对 Svelte 充满好奇的 React 开发人员,在属性传递上 Svelte 没有什么新奇之处。而在接收属性时 Svelte 有点点不一样,后面将进行介绍。
为了让这个应用正常工作,每次点击按钮时,必须让 App 组件的 count 状态值增1。因此需要一个机制来将数据从子组件传递给父组件。
前面已经通过将 handleClick() 函数作为属性传递给 Button 组件。
接下来马上要开始编写的这个属于 App 组件的函数。当把它作为属性传递给 Button 子组件,Button 组件就能在每次被点击时调用这个函数。这就是 App 组件能响应其子组件状态变更的原因。
handleClick() 这个函数负责用来更新 App 组件的 count 和 color 状态值。
在 App.svelte 中编写 handleClick 函数代码如下:
const colors = ['#00ff00', '#ff0000', '#0000ff'];
let handleClick = () => {
count++;
color = colors[Math.floor(Math.random() * 3)];
}
在 App.js 中编写 handleClick 函数代码如下:
const colors = ['#00ff00', '#ff0000', '#0000ff'];
let handleClick = () => {
setCount(count+1);
setColor(colors[Math.floor(Math.random() * 3)]);
}
在 React 需要使用早先声明的 setCount() 和 setColor() 方法来更新状态值,而 Svelte 则可以直接更新。
现在我们可以开始编写 Heading 组件了。
Heading 组件显示这个应用的标题以及点击计数器。这不是一个有状态的组件,其接收状态值 count 来显示按钮点击次数。
在 Svelte 项目的 src 文件夹中创建一个名为 Heading.svelte 的文件。
同样的在 React 项目的 src 文件夹中创建新文件 Heading.js.
拷贝如下代码到 Heading.svelte 文件:
<script>
export let count;
</script>
<h1>Hello, I am a Svelte App!</h1>
<h2>The following button has been clicked {count} times.</h2>
请注意看上述代码中 <script>
里的代码。这行代码告诉 Svelte 说,该组件将接收一个名为 count 的属性。
这样就可以在 Heading 组件的 HTML 模板中直接显示 count 这个属性。
这个写法稍微有点点奇怪,但在文件顶部直接声明属性的方式看起来不错,而且可以直接使用这个属性。
切换到 Heading.js 文件,拷贝如下内容到该文件:
// ConardLi
function Heading({ count }) {
return (
<div>
<h1>Hello, I am a React App!</h1>
<h2>The following button has been clicked {count} times.</h2>
</div>
)
}
export default Heading;
这段代码创建一个新的名为 Heading 函数式组件,该组件有一个参数 { count }, 这是从传递给组件的 props 对象中提取出来的。
Button 组件在界面上显示一个按钮,同时接收两个属性,分别是用来定义颜色的 color 和在点击时触发的 handleClick() 函数。
在 Svelte 项目的 src 文件夹中创建新文件 Button.svelte.
在 React 项目的 src 文件夹中创建新文件 Button.js.
类似点击和其他鼠标事件等交互式事件的侦听上,Svelte 和 React 的做法有一些不同。
拷贝如下代码到 Button.svelte:
// ConardLi
<script>
export let handleClick;
export let color;
</script>
<button style="--color: {color}" on:click={handleClick}>
Click me!
</button>
上述代码中两个属性都是在顶部的 <script>
标签中定义的。
然后它创建了一个按钮。请注意第 6 行代码的语法,忽略掉下一节要介绍的样式部分,直接看按钮点击的事件侦听器,它跟以往使用的习惯不同。
Svelte 使用一个 on: 指令来给 DOM 元素添加事件侦听器。Svelte 使用非常简洁方法进行事件修改,甚至可以只在按钮首次点击时触发。更详细的关键事件的触发请阅读 dispatch your own component events
这篇文档。
拷贝如下代码到 Button.js:
function Button({ color, handleClick }) {
return (
<button style={styles} onClick={handleClick}>
Click me!
</button>
)
}
export default Button;
如果服务依然运行中,将会看到这里有报错信息,别担心,下面我们将通过添加 styles 对象来可以解决这个问题。
上述代码创建一个名为 Button() 的函数式组件,同时接收一个参数 props, 参数包含两个属性 color 和 handleClick。handleClick() 函数在 handleClick 属性上定义,可以在 JSX 上使用一个标准的 onClick 事件来触发。
在这个应用中 Button 组件介绍一个颜色值作为属性,该颜色值就是按钮的背景色。
Svelte 的动态样式没有我期望的那么直接。
很不幸,不能直接在 <style>
标签中使用属性值。不过可以使用组件的 HTML 作为在 JavaScript 和 CSS 之间通讯的方法。
在 Button 组件 Button.svelte 的 HTML 代码下方增加如下代码:
<style>
button {
color: white;
background-color: var(--color);
}
</style>
background-color 样式属性不能直接引用 color 属性的值,它引用的是一个名为 color的样式变量,这个样式变量在前面的 HTML 代码中通过 style="--color: {color}" 进行定义。
这个做法有一点点笨拙,但考虑到这个样式仅在组件内有效,我们也是可以接受的。当然了,也可以定义全局样式,具体请阅读 global CSS 这篇文档:https://svelte.dev/docs#style。
在 React 中可以有很多种方法给组件添加样式。直接在元素上编写样式是最常用的方法。
要在 JSX 中使用内嵌样式,可以使用样式创建一个对象,然后赋值给元素的 style 属性,剩下的部分前面已经实现过了。
在 Button() 函数中的 return 语句前面添加如下代码来创建 styles 对象:
const styles = {
backgroundColor: color,
color: '#ffffff'
}
保存所有文件,如果应用还没有启动,那现在就各自启动服务 ( Svelte : npm run dev, React : npm start)。然后打开浏览器的两个 Tab 分别访问 localhost:5000 和 localhost:3000 。
依次点击两个页面的按钮,看看效果
图片
图片
从运行效果来看,Svelte 和 React 似乎在样式上有点不同,但是功能已经完成了。你对这两个框架的感觉怎样呢?
本文翻译自 React vs. Svelte: Comparing the Basics (twilio.com):https://www.twilio.com/blog/react-svelte-comparing-basics
这是一次对 Svelte
有趣的探索,到目前位置二者能力差不多。Svelte
的模板语言非常有趣,特别是 on: 指令。实话实说我很怀念编写 HTML 模板的日子。我一定会用 Svelte
来编写更多的应用,同时我也将深入了解诸如生命周期和数据绑定方面的能力,这些对 React 当前阶段来说还是有点痛苦的。
如果你也在学习 Svelte
的话,别忘了跟大家分享。
你觉得哪个更好用呢?
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/TPLsmkn08C0g_yq0Poodig
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。