比较Svelte并反应

2021-03-26 19:43:11

去年我创建了Pomodone,这是一个小型时间跟踪应用,基于Pomodoro技术的工作时间为25分钟的间隔。它' s一个非常基本的应用程序;它有一个25分钟的计时器(在Web工作者中运行)并保存您的" Poms&#34的历史;到一个小的firebase数据库。我最初使用React(井实际上)建立它,但我开始使用Svelte播放,并决定在Svelte中重建应用程序可能是博客关于库之间的相似性和差异的好方法。

这不是声明svelte的帖子比反应更好,或反之亦然。这是一个' ll告诉你我的偏好的帖子,以及我发现更容易或框架更容易或更难。我不是在这里选择一场战斗!此外,POMODONE是难以置信的应用程序,可用于通过其鞋面完全放置反应或智能。将这篇文章作为评论,根据我的经验扔在一起,专注于将这些组件放在一起的开发人员体验。

该应用程序使用Firebase身份验证通过其GitHub或Google帐户登录用户。我喜欢Firebase身份验证,它'这是一个简单的方法,可以将验证添加到侧面项目。

反应' s钩子是包装的好方法;我创建了一个USECURRENTUSER挂钩,侦听身份验证更改并相应地设置某些状态。然后,当注意到认证更改时,我可以信任重新渲染重新渲染。

Export Const UseCurrentUser =()=> {const [currentUser,setCurrentUser] = useState(未定义)使用effeffect(()=> {return firebase。auth()。OnauthstateChanged((详细信息)=> {setCurrentUser(详细信息?{displayname:详细信息.displayname,提供者:{ ' google.com':' google',' github.com':' github',} [详细信息.providerdata [0] .providerid ],UID:详细信息.UID,}:null)})},[])返回[普照用户]}

这很好;它'低的努力,让任何组件快速访问当前用户。这唯一的缺点是您可能有许多OnauthstateChanged听众;我可以通过仅绑定一个侦听器,或者通过将当前用户放在上下文中来缓解这一点。

谈论上下文,'较近我带有Svelte的方法,并使用可写商店。

Export Const CurrentUser =可写()导出const listenforauthchanges =()=> {返回Firebase。 auth()。 OnauthStateChanged((详细信息)=> {if(详细信息){uscuserer。设置({displayname:详细信息.displayname,提供程序:{' google.com':'谷歌',&# 39; github.com':' github',} [详细信息.providerdata [0] .providerid],uid:详细信息.uid,})} else {lustuser。set(null)}}) }

在顶层Svelte组件中,我可以在onmount内调用此,这将在挂载组件时运行一次(返回该函数,因此我们在删除组件时取消订阅,就像使用的是使用yeffect excume yours yours yours yourse yeffect)。

现在在我的svelte代码库中的任何地方,一个组件可以导入普照用户可写存储,并相应行动。我喜欢的是普照用户ISN' t a值,它'它的一家商店,因此您可以完全控制您如何处理它。您可以订阅它并使用状态更改手动控制:

或者,如果您想要仔细阅读最新值,则可以使用$前缀为$:

这是一些Svelte' s语法技巧开始发光的地方;这款美元前缀技巧自动向您订购商店'最新值。我都喜欢和不喜欢这个;它一旦你知道,它就是一个很好的语法,但它'有点奇怪作为初学者习惯。但是,我喜欢那个svelte并在每次需要读取该值时让我使用订阅API。

就基本身份验证而言,这两个库似乎都在这里采取类似的方法。虽然术语和精确语法略有不同,但两者都允许您订阅Firebase侦听器并在验证状态更改时更新。反应' s的上下文和svelte' s商店对他们的图书馆发挥几乎相同的角色。

Pomodone必须保持25分钟的计时器,并尽量尽可能准确。如果背景(例如,不是聚焦选项卡),大多数浏览器将降低其SetTimeout调用的优先级,而不是严格运行时间。大部分时间在网上这个都是一个大量的交易,但是当用户通过你的应用程序跟踪25分钟的工作时,它是!此外,在25分钟的过程中,任何轻微的时间漂移​​都会导致最后一次更远。但是,如果这些超时被移动到Web工作者,则它们应该运行时间而不会被浏览器进行除见所要求。

因此,在我的跟踪器组件中,我需要实例化一个Web工作者,发送它消息并接收数据(例如剩余时间)。这是我发现的一个领域,其中" admin重#34;比velte;因为每次组件重新渲染时重新执行React组件,所以您可以轻松地结束成千上万的工人!它'对于使用valef来避免对您创建的工人的参考来避免这个问题。

然后创建一个使用效果钩子,如果需要,将实例化工作者,并绑定事件侦听器以侦听消息:

使用effeffect(()=> {if(!worker .current){worlter .current = new(warlerull)窗口.worker = worker .current} const onmessage =(事件)=> {if(事件.data .name = =='勾选'){setCurrentPom((currentPom)=>({... currentPom,秒数:事件.data .counter,})}如果(事件.data .name === ' start'){//在这里删除的更多分支以保存空间...}}}工作者.Current。addeventListener('消息',onmessage)return()=> {工人。当前。RemoveeventListener('消息',onmessage)},[普查队])

然后,当用户击中"开始"按钮,我必须发送工作者消息:

Svelte看起来很相似,但有两个小变化,个人使Svelte代码更容易阅读,在我看来:

我们不必将工人保留在Useref中,可以将其分配给变量。

我们可以更轻松地将事件侦听器代码更容易地输出,因为该函数Won' t然后成为一个使用effeffect的依赖 - 那么我们必须将其包装在USECALLBALL中。

让工作者onmount(()=> {worler = new(workerull)工作者。addeventlistener(' message',onworkermessage)return()=> {worlter。removeeventlistener('消息' ,onworkermessage)}})

我们也不要使用React' s setx(oldx => newx)惯例来设置状态,并且可以只是突变局部变量:

函数onWorkermessage(事件){if(事件.data .name ==='勾选'){currentpom = {... currentpom,stickeRemaining:事件.data .counter,}} else(事件.data .name ===' start'){//更多分支机构删除以保存空间...}}

这里'我开始有妙语的偏好;这两者非常相似,但是一旦我习惯了Svelte,我发现那种反应感觉像跳过箍一样。您可以创建一个工人实例,它必须进入USERF,然后您可以' t轻松地将代码拉出到一个函数中,而无需USECALLBALL,因此它可以是对使用效果的安全依赖性。使用svelte我写代码'靠近" plain" JavaScript,而在反应原始中将更多的代码造成更多代码。

反应的一部分是我' Ve始终冠军的反应是它的' s只是javascript。我喜欢那个反应你不要使用不同的模板语法,而是与svelte' s模板语言相比嵌入了javascript:

{PomsforCurrentday。地图(entrydata,index)=> {const iteftat =格式(new(entrydata .timefinished),' h:mm:ss')返回{index + 1}})}

< ul class =" poms-list" > {#ach CurrandayPoMS为值,索引}< li标题= {`以$ {格式完成(重大值。 {index + 1}< / Li> {/每个}< / ul>

我对Svelte&#39的模板感到惊喜;在过去的我' ve发现模板语言压倒性和不灵活,但Svelte提供了适量的模板,同时也可以使用JavaScript。也就是说,我将永远发现反应'至少在我的头上,我认为对熟悉正在学习图书馆的javascript的人更友好。

但是,在渲染组件(感觉非常JSX类似)时,Svelte确实有一些很好的触摸它的语法。我最喜欢的是折叠道具的能力:

React要求我们使用IndeFeffect和其他钩子,因为它完全控制了所有代码如何运行并在重新呈现组件时重新运行代码。 Svelte是不同的,因为默认情况下,大多数代码只能运行一次; CONSOLE.LOG(' foo')在组件中只在第一次呈现该组件时运行。在反应中,它将运行很多次。

反应' S重新渲染方法有其上限:假设您正在进行大量数据列表,并运行一些功能以将其转换为您可以呈现的数据。在您的组件中反应,您可以写入:

并且这将始终是最新的 - 如果用户提供新的Props.InputData,则组件将重新呈现,输出将更新。

这里首次呈现组件的输出将呈现,但根本不会更新。我们可以通过使用$:标签语法以两种方式解决这一方式,它将代码标记为反应,或者通过将我们的转换逻辑移动到模板中:

这是Svelte拍摄JavaScript语法的另一个例子,并使用它略有不同的含义;它告诉Svelte声明是反应性的,如果任何进口改变,应重新计算。您也可以称之为A"计算的属性"第二个解决方案只需将逻辑移动到模板中,从而确保当组件重新渲染逻辑时再次执行。在我的时间与svelte这是我大部分时间都走了的方法,经常将逻辑拉到一个函数:

来自智慧的反应,这确实很多次,但对我来说,我现在更喜欢Svelte' S的方法,特别是因为它去除了围绕使用的一些样板。

组件组成是使基于组件基于组件的框架且诸如反应和Svelte解决方案的东西的巨大部分。 React' sendrain prop使其很容易渲染任何提供的内容:

(如果你没有阅读它,那么组合物的反应指南都值得一读)。

当涉及多个孩子时,他们采取不同的方法,这就是我发现自己更喜欢智慧的地方。反应表明通过多个道具:

功能框(道具){return({props .left} {props .right})}函数app(){return}

一个抱着我的方法是这种方法,你还失去了你的视觉线索和#39;将孩子们传入盒子组件;当你像我们一样渲染它们时,他们现在仍然嵌套在盒子里。它现在由您读到用于提供儿童的道具和位置。它&#39轻松在这个虚设的例子上完成,但在&#34中更难;现实世界"应用程序 - 或者至少,我发现它更难!

svelte' s方法是定义具有显式名称的多个插槽,让用户提供应该填充这些插槽的元素:

我喜欢这种方法更多,因为我可以扫描渲染框组件的代码,并且轻松发现它需要两个孩子。如果盒子接受了任何道具,它们在开口< box>标签,他们会与任何儿童道具不同。

我的偏好通过我每天在工作建筑Web组件上花费的事实偏见,所以Svelte' S方法对Web组件中的插槽感觉非常熟悉。

我喜欢Svelte对造型有意义;特别是在像丘陵等小的侧面项目的背景下,它很高兴为我做出这个决定。 Svelte还可以检测到未使用的CSS的事实是很大的,这是我怀疑i&#39的原因之一; LL在未来的项目中为Svelte达到更多。

这不是一个缺点的反应; React' S优势之一是它让您控制如此多,插槽在您的环境中反应,但我喜欢那个Svelte附带一个很好的CSS故事。

我喜欢svelte的一个小功能是我如何有条件地将类应用于元素:

这将应用该类对元素有效,但仅当值是achiach是真实的。这读得很好,很清楚,很棒,它出来了盒子里。

我使用ClassNames在反应中实现了类似的功能,而且它是一个很好的解决方案,但我喜欢Svelte提供了这个盒子。

与条件类类似,Svelte包在一些额外的实用程序中,用于以修饰程序的形式绑定事件侦听器。这些允许您修改事件侦听器以便询问Svelte以包含常用功能,例如调用event.preventdefault()。

< script>函数单击(){//无需防止我们自己//逻辑}}< / script> <按钮:单击| preventdefault = {click}>点击我! < /按钮>

我喜欢反应和svelte。让我在一个码比中与其中任何一个,我享受它,享受它,富有成效,快乐地将新功能放在一起或修复错误。我的反应和其他人在Svelte中有一方的项目,我' m毫不急于将任何一个转换为另一个。反应和Svelte在许多方面非常相似,但是我发现的是,在它们不同的一切方面,我更喜欢Svelte。 POMODONE的CODEBASE对SVelte中的ME更为有意义,而不是反应。我发现它更容易导航和工作。

如果我总结为什么在一句话中,它' s是因为我没有错过使用的使用。我理解为什么它存在,我理解这种方法会采取的,并且有利于其方法。但是写复杂的反应组件感觉更像是管理员;一个不断担心我' ll错过了我的使用次数呼叫中的依赖,最终崩溃了我的浏览器会话。用svelte我没有' t有那种挥之不去的感觉,那个'那是我的' vere来享受。当我用有用的API需要时,svelte是在那里,但是当我把我的应用程序放在一起时,逐渐消失。

如果您喜欢此帖子,请加入时事通讯以获取新内容的更新😎。